Merge branch 'dev' into fix/grafting-pre-reqs

This commit is contained in:
nickofolas 2022-03-30 21:12:44 -04:00
commit a80693dab2
51 changed files with 3511 additions and 3177 deletions

42
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
letter_to_fandom.com Normal file

@ -0,0 +1 @@
I want the wiki here https://bitburner.fandom.com/wiki/Bitburner_Wiki taken down please.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -129,6 +129,6 @@
"electron:packager-win": "electron-packager .package bitburner --platform win32 --arch x64 --out .build --overwrite --icon .package/icon.png", "electron:packager-win": "electron-packager .package bitburner --platform win32 --arch x64 --out .build --overwrite --icon .package/icon.png",
"electron:packager-mac": "electron-packager .package bitburner --platform darwin --arch x64 --out .build --overwrite --icon .package/icon.png", "electron:packager-mac": "electron-packager .package bitburner --platform darwin --arch x64 --out .build --overwrite --icon .package/icon.png",
"electron:packager-linux": "electron-packager .package bitburner --platform linux --arch x64 --out .build --overwrite --icon .package/icon.png", "electron:packager-linux": "electron-packager .package bitburner --platform linux --arch x64 --out .build --overwrite --icon .package/icon.png",
"allbuild": "npm run build && npm run electron && git add --all && git commit -m \"allbuild commit $(which git)\" && git push -f -u origin dev" "allbuild": "npm run build && npm run electron && git add --all && git commit -m \"allbuild commit $(git rev-parse --short HEAD)\" && git push -f -u origin dev"
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,234 +1,121 @@
export const AugmentationNames: { export enum AugmentationNames {
Targeting1: string; Targeting1 = "Augmented Targeting I",
Targeting2: string; Targeting2 = "Augmented Targeting II",
Targeting3: string; Targeting3 = "Augmented Targeting III",
SyntheticHeart: string; SyntheticHeart = "Synthetic Heart",
SynfibrilMuscle: string; SynfibrilMuscle = "Synfibril Muscle",
CombatRib1: string; CombatRib1 = "Combat Rib I",
CombatRib2: string; CombatRib2 = "Combat Rib II",
CombatRib3: string; CombatRib3 = "Combat Rib III",
NanofiberWeave: string; NanofiberWeave = "Nanofiber Weave",
SubdermalArmor: string; SubdermalArmor = "NEMEAN Subdermal Weave",
WiredReflexes: string; WiredReflexes = "Wired Reflexes",
GrapheneBoneLacings: string; GrapheneBoneLacings = "Graphene Bone Lacings",
BionicSpine: string; BionicSpine = "Bionic Spine",
GrapheneBionicSpine: string; GrapheneBionicSpine = "Graphene Bionic Spine Upgrade",
BionicLegs: string; BionicLegs = "Bionic Legs",
GrapheneBionicLegs: string; GrapheneBionicLegs = "Graphene Bionic Legs Upgrade",
SpeechProcessor: string; SpeechProcessor = "Speech Processor Implant",
TITN41Injection: string; TITN41Injection = "TITN-41 Gene-Modification Injection",
EnhancedSocialInteractionImplant: string; EnhancedSocialInteractionImplant = "Enhanced Social Interaction Implant",
BitWire: string; BitWire = "BitWire",
ArtificialBioNeuralNetwork: string; ArtificialBioNeuralNetwork = "Artificial Bio-neural Network Implant",
ArtificialSynapticPotentiation: string; ArtificialSynapticPotentiation = "Artificial Synaptic Potentiation",
EnhancedMyelinSheathing: string; EnhancedMyelinSheathing = "Enhanced Myelin Sheathing",
SynapticEnhancement: string; SynapticEnhancement = "Synaptic Enhancement Implant",
NeuralRetentionEnhancement: string; NeuralRetentionEnhancement = "Neural-Retention Enhancement",
DataJack: string; DataJack = "DataJack",
ENM: string; ENM = "Embedded Netburner Module",
ENMCore: string; ENMCore = "Embedded Netburner Module Core Implant",
ENMCoreV2: string; ENMCoreV2 = "Embedded Netburner Module Core V2 Upgrade",
ENMCoreV3: string; ENMCoreV3 = "Embedded Netburner Module Core V3 Upgrade",
ENMAnalyzeEngine: string; ENMAnalyzeEngine = "Embedded Netburner Module Analyze Engine",
ENMDMA: string; ENMDMA = "Embedded Netburner Module Direct Memory Access Upgrade",
Neuralstimulator: string; Neuralstimulator = "Neuralstimulator",
NeuralAccelerator: string; NeuralAccelerator = "Neural Accelerator",
CranialSignalProcessorsG1: string; CranialSignalProcessorsG1 = "Cranial Signal Processors - Gen I",
CranialSignalProcessorsG2: string; CranialSignalProcessorsG2 = "Cranial Signal Processors - Gen II",
CranialSignalProcessorsG3: string; CranialSignalProcessorsG3 = "Cranial Signal Processors - Gen III",
CranialSignalProcessorsG4: string; CranialSignalProcessorsG4 = "Cranial Signal Processors - Gen IV",
CranialSignalProcessorsG5: string; CranialSignalProcessorsG5 = "Cranial Signal Processors - Gen V",
NeuronalDensification: string; NeuronalDensification = "Neuronal Densification",
NeuroreceptorManager: string; NeuroreceptorManager = "Neuroreceptor Management Implant",
NuoptimalInjectorImplant: string; NuoptimalInjectorImplant = "Nuoptimal Nootropic Injector Implant",
SpeechEnhancement: string; SpeechEnhancement = "Speech Enhancement",
FocusWire: string; FocusWire = "FocusWire",
PCDNI: string; PCDNI = "PC Direct-Neural Interface",
PCDNIOptimizer: string; PCDNIOptimizer = "PC Direct-Neural Interface Optimization Submodule",
PCDNINeuralNetwork: string; PCDNINeuralNetwork = "PC Direct-Neural Interface NeuroNet Injector",
PCMatrix: string; PCMatrix = "PCMatrix",
ADRPheromone1: string; ADRPheromone1 = "ADR-V1 Pheromone Gene",
ADRPheromone2: string; ADRPheromone2 = "ADR-V2 Pheromone Gene",
ShadowsSimulacrum: string; ShadowsSimulacrum = "The Shadow's Simulacrum",
HacknetNodeCPUUpload: string; HacknetNodeCPUUpload = "Hacknet Node CPU Architecture Neural-Upload",
HacknetNodeCacheUpload: string; HacknetNodeCacheUpload = "Hacknet Node Cache Architecture Neural-Upload",
HacknetNodeNICUpload: string; HacknetNodeNICUpload = "Hacknet Node NIC Architecture Neural-Upload",
HacknetNodeKernelDNI: string; HacknetNodeKernelDNI = "Hacknet Node Kernel Direct-Neural Interface",
HacknetNodeCoreDNI: string; HacknetNodeCoreDNI = "Hacknet Node Core Direct-Neural Interface",
NeuroFluxGovernor: string; NeuroFluxGovernor = "NeuroFlux Governor",
Neurotrainer1: string; Neurotrainer1 = "Neurotrainer I",
Neurotrainer2: string; Neurotrainer2 = "Neurotrainer II",
Neurotrainer3: string; Neurotrainer3 = "Neurotrainer III",
Hypersight: string; Hypersight = "HyperSight Corneal Implant",
LuminCloaking1: string; LuminCloaking1 = "LuminCloaking-V1 Skin Implant",
LuminCloaking2: string; LuminCloaking2 = "LuminCloaking-V2 Skin Implant",
HemoRecirculator: string; HemoRecirculator = "HemoRecirculator",
SmartSonar: string; SmartSonar = "SmartSonar Implant",
PowerRecirculator: string; PowerRecirculator = "Power Recirculation Core",
QLink: string; QLink = "QLink",
TheRedPill: string; TheRedPill = "The Red Pill",
SPTN97: string; SPTN97 = "SPTN-97 Gene Modification",
HiveMind: string; HiveMind = "ECorp HVMind Implant",
CordiARCReactor: string; CordiARCReactor = "CordiARC Fusion Reactor",
SmartJaw: string; SmartJaw = "SmartJaw",
Neotra: string; Neotra = "Neotra",
Xanipher: string; Xanipher = "Xanipher",
nextSENS: string; nextSENS = "nextSENS Gene Modification",
OmniTekInfoLoad: string; OmniTekInfoLoad = "OmniTek InfoLoad",
PhotosyntheticCells: string; PhotosyntheticCells = "Photosynthetic Cells",
Neurolink: string; Neurolink = "BitRunners Neurolink",
TheBlackHand: string; TheBlackHand = "The Black Hand",
UnstableCircadianModulator: string; UnstableCircadianModulator = "Unstable Circadian Modulator",
CRTX42AA: string; CRTX42AA = "CRTX42-AA Gene Modification",
Neuregen: string; Neuregen = "Neuregen Gene Modification",
CashRoot: string; CashRoot = "CashRoot Starter Kit",
NutriGen: string; NutriGen = "NutriGen Implant",
INFRARet: string; INFRARet = "INFRARET Enhancement",
DermaForce: string; DermaForce = "DermaForce Particle Barrier",
GrapheneBrachiBlades: string; GrapheneBrachiBlades = "Graphene BrachiBlades Upgrade",
GrapheneBionicArms: string; GrapheneBionicArms = "Graphene Bionic Arms Upgrade",
BrachiBlades: string; BrachiBlades = "BrachiBlades",
BionicArms: string; BionicArms = "Bionic Arms",
SNA: string; SNA = "Social Negotiation Assistant (S.N.A)",
HydroflameLeftArm: string; HydroflameLeftArm = "Hydroflame Left Arm",
EsperEyewear: string; EsperEyewear = "EsperTech Bladeburner Eyewear",
EMS4Recombination: string; EMS4Recombination = "EMS-4 Recombination",
OrionShoulder: string; OrionShoulder = "ORION-MKIV Shoulder",
HyperionV1: string; HyperionV1 = "Hyperion Plasma Cannon V1",
HyperionV2: string; HyperionV2 = "Hyperion Plasma Cannon V2",
GolemSerum: string; GolemSerum = "GOLEM Serum",
VangelisVirus: string; VangelisVirus = "Vangelis Virus",
VangelisVirus3: string; VangelisVirus3 = "Vangelis Virus 3.0",
INTERLINKED: string; INTERLINKED = "I.N.T.E.R.L.I.N.K.E.D",
BladeRunner: string; BladeRunner = "Blade's Runners",
BladeArmor: string; BladeArmor = "BLADE-51b Tesla Armor",
BladeArmorPowerCells: string; BladeArmorPowerCells = "BLADE-51b Tesla Armor: Power Cells Upgrade",
BladeArmorEnergyShielding: string; BladeArmorEnergyShielding = "BLADE-51b Tesla Armor: Energy Shielding Upgrade",
BladeArmorUnibeam: string; BladeArmorUnibeam = "BLADE-51b Tesla Armor: Unibeam Upgrade",
BladeArmorOmnibeam: string; BladeArmorOmnibeam = "BLADE-51b Tesla Armor: Omnibeam Upgrade",
BladeArmorIPU: string; BladeArmorIPU = "BLADE-51b Tesla Armor: IPU Upgrade",
BladesSimulacrum: string; BladesSimulacrum = "The Blade's Simulacrum",
StaneksGift1: string;
StaneksGift2: string;
StaneksGift3: string;
} = {
Targeting1: "Augmented Targeting I",
Targeting2: "Augmented Targeting II",
Targeting3: "Augmented Targeting III",
SyntheticHeart: "Synthetic Heart",
SynfibrilMuscle: "Synfibril Muscle",
CombatRib1: "Combat Rib I",
CombatRib2: "Combat Rib II",
CombatRib3: "Combat Rib III",
NanofiberWeave: "Nanofiber Weave",
SubdermalArmor: "NEMEAN Subdermal Weave",
WiredReflexes: "Wired Reflexes",
GrapheneBoneLacings: "Graphene Bone Lacings",
BionicSpine: "Bionic Spine",
GrapheneBionicSpine: "Graphene Bionic Spine Upgrade",
BionicLegs: "Bionic Legs",
GrapheneBionicLegs: "Graphene Bionic Legs Upgrade",
SpeechProcessor: "Speech Processor Implant",
TITN41Injection: "TITN-41 Gene-Modification Injection",
EnhancedSocialInteractionImplant: "Enhanced Social Interaction Implant",
BitWire: "BitWire",
ArtificialBioNeuralNetwork: "Artificial Bio-neural Network Implant",
ArtificialSynapticPotentiation: "Artificial Synaptic Potentiation",
EnhancedMyelinSheathing: "Enhanced Myelin Sheathing",
SynapticEnhancement: "Synaptic Enhancement Implant",
NeuralRetentionEnhancement: "Neural-Retention Enhancement",
DataJack: "DataJack",
ENM: "Embedded Netburner Module",
ENMCore: "Embedded Netburner Module Core Implant",
ENMCoreV2: "Embedded Netburner Module Core V2 Upgrade",
ENMCoreV3: "Embedded Netburner Module Core V3 Upgrade",
ENMAnalyzeEngine: "Embedded Netburner Module Analyze Engine",
ENMDMA: "Embedded Netburner Module Direct Memory Access Upgrade",
Neuralstimulator: "Neuralstimulator",
NeuralAccelerator: "Neural Accelerator",
CranialSignalProcessorsG1: "Cranial Signal Processors - Gen I",
CranialSignalProcessorsG2: "Cranial Signal Processors - Gen II",
CranialSignalProcessorsG3: "Cranial Signal Processors - Gen III",
CranialSignalProcessorsG4: "Cranial Signal Processors - Gen IV",
CranialSignalProcessorsG5: "Cranial Signal Processors - Gen V",
NeuronalDensification: "Neuronal Densification",
NeuroreceptorManager: "Neuroreceptor Management Implant",
NuoptimalInjectorImplant: "Nuoptimal Nootropic Injector Implant",
SpeechEnhancement: "Speech Enhancement",
FocusWire: "FocusWire",
PCDNI: "PC Direct-Neural Interface",
PCDNIOptimizer: "PC Direct-Neural Interface Optimization Submodule",
PCDNINeuralNetwork: "PC Direct-Neural Interface NeuroNet Injector",
PCMatrix: "PCMatrix",
ADRPheromone1: "ADR-V1 Pheromone Gene",
ADRPheromone2: "ADR-V2 Pheromone Gene",
ShadowsSimulacrum: "The Shadow's Simulacrum",
HacknetNodeCPUUpload: "Hacknet Node CPU Architecture Neural-Upload",
HacknetNodeCacheUpload: "Hacknet Node Cache Architecture Neural-Upload",
HacknetNodeNICUpload: "Hacknet Node NIC Architecture Neural-Upload",
HacknetNodeKernelDNI: "Hacknet Node Kernel Direct-Neural Interface",
HacknetNodeCoreDNI: "Hacknet Node Core Direct-Neural Interface",
NeuroFluxGovernor: "NeuroFlux Governor",
Neurotrainer1: "Neurotrainer I",
Neurotrainer2: "Neurotrainer II",
Neurotrainer3: "Neurotrainer III",
Hypersight: "HyperSight Corneal Implant",
LuminCloaking1: "LuminCloaking-V1 Skin Implant",
LuminCloaking2: "LuminCloaking-V2 Skin Implant",
HemoRecirculator: "HemoRecirculator",
SmartSonar: "SmartSonar Implant",
PowerRecirculator: "Power Recirculation Core",
QLink: "QLink",
TheRedPill: "The Red Pill",
SPTN97: "SPTN-97 Gene Modification",
HiveMind: "ECorp HVMind Implant",
CordiARCReactor: "CordiARC Fusion Reactor",
SmartJaw: "SmartJaw",
Neotra: "Neotra",
Xanipher: "Xanipher",
nextSENS: "nextSENS Gene Modification",
OmniTekInfoLoad: "OmniTek InfoLoad",
PhotosyntheticCells: "Photosynthetic Cells",
Neurolink: "BitRunners Neurolink",
TheBlackHand: "The Black Hand",
UnstableCircadianModulator: "Unstable Circadian Modulator",
CRTX42AA: "CRTX42-AA Gene Modification",
Neuregen: "Neuregen Gene Modification",
CashRoot: "CashRoot Starter Kit",
NutriGen: "NutriGen Implant",
INFRARet: "INFRARET Enhancement",
DermaForce: "DermaForce Particle Barrier",
GrapheneBrachiBlades: "Graphene BrachiBlades Upgrade",
GrapheneBionicArms: "Graphene Bionic Arms Upgrade",
BrachiBlades: "BrachiBlades",
BionicArms: "Bionic Arms",
SNA: "Social Negotiation Assistant (S.N.A)",
HydroflameLeftArm: "Hydroflame Left Arm",
EsperEyewear: "EsperTech Bladeburner Eyewear",
EMS4Recombination: "EMS-4 Recombination",
OrionShoulder: "ORION-MKIV Shoulder",
HyperionV1: "Hyperion Plasma Cannon V1",
HyperionV2: "Hyperion Plasma Cannon V2",
GolemSerum: "GOLEM Serum",
VangelisVirus: "Vangelis Virus",
VangelisVirus3: "Vangelis Virus 3.0",
INTERLINKED: "I.N.T.E.R.L.I.N.K.E.D",
BladeRunner: "Blade's Runners",
BladeArmor: "BLADE-51b Tesla Armor",
BladeArmorPowerCells: "BLADE-51b Tesla Armor: Power Cells Upgrade",
BladeArmorEnergyShielding: "BLADE-51b Tesla Armor: Energy Shielding Upgrade",
BladeArmorUnibeam: "BLADE-51b Tesla Armor: Unibeam Upgrade",
BladeArmorOmnibeam: "BLADE-51b Tesla Armor: Omnibeam Upgrade",
BladeArmorIPU: "BLADE-51b Tesla Armor: IPU Upgrade",
BladesSimulacrum: "The Blade's Simulacrum",
StaneksGift1: "Stanek's Gift - Genesis", StaneksGift1 = "Stanek's Gift - Genesis",
StaneksGift2: "Stanek's Gift - Awakening", StaneksGift2 = "Stanek's Gift - Awakening",
StaneksGift3: "Stanek's Gift - Serenity", StaneksGift3 = "Stanek's Gift - Serenity",
//Wasteland Augs //Wasteland Augs
//PepBoy: "P.E.P-Boy", Plasma Energy Projection System //PepBoy: "P.E.P-Boy", Plasma Energy Projection System
//PepBoyForceField Generates plasma force fields //PepBoyForceField Generates plasma force fields
//PepBoyBlasts Generate high density plasma concussive blasts //PepBoyBlasts Generate high density plasma concussive blasts
//PepBoyDataStorage STore more data on pep boy, //PepBoyDataStorage STore more data on pep boy,
}; }

@ -82,7 +82,9 @@ BitNodes["BitNode2"] = new BitNode(
<br /> <br />
The amount of money gained from crimes and Infiltration is tripled The amount of money gained from crimes and Infiltration is tripled
<br /> <br />
Certain Factions ({FactionNames.SlumSnakes}, {FactionNames.Tetrads}, {FactionNames.TheSyndicate}, {FactionNames.TheDarkArmy}, {FactionNames.SpeakersForTheDead}, {FactionNames.NiteSec}, {FactionNames.TheBlackHand}) give the player the ability to form and manage their own gangs. These gangs will earn the player money and Certain Factions ({FactionNames.SlumSnakes}, {FactionNames.Tetrads}, {FactionNames.TheSyndicate},{" "}
{FactionNames.TheDarkArmy}, {FactionNames.SpeakersForTheDead}, {FactionNames.NiteSec}, {FactionNames.TheBlackHand}
) give the player the ability to form and manage their own gangs. These gangs will earn the player money and
reputation with the corresponding Faction reputation with the corresponding Faction
<br /> <br />
Every Augmentation in the game will be available through the Factions listed above Every Augmentation in the game will be available through the Factions listed above
@ -225,15 +227,15 @@ BitNodes["BitNode6"] = new BitNode(
"Like Tears in Rain", "Like Tears in Rain",
( (
<> <>
In the middle of the 21st century, {FactionNames.OmniTekIncorporated} began designing and manufacturing advanced synthetic In the middle of the 21st century, {FactionNames.OmniTekIncorporated} began designing and manufacturing advanced
androids, or Synthoids for short. They achieved a major technological breakthrough in the sixth generation of synthetic androids, or Synthoids for short. They achieved a major technological breakthrough in the sixth
their Synthoid design, called MK-VI, by developing a hyperintelligent AI. Many argue that this was the first generation of their Synthoid design, called MK-VI, by developing a hyperintelligent AI. Many argue that this was
sentient AI ever created. This resulted in Synthoid models that were stronger, faster, and more intelligent than the first sentient AI ever created. This resulted in Synthoid models that were stronger, faster, and more
the humans that had created them. intelligent than the humans that had created them.
<br /> <br />
<br /> <br />
In this BitNode you will be able to access the {FactionNames.Bladeburners} Division at the NSA, which provides a new mechanic for In this BitNode you will be able to access the {FactionNames.Bladeburners} Division at the NSA, which provides a
progression. Furthermore: new mechanic for progression. Furthermore:
<br /> <br />
<br /> <br />
Hacking and Hacknet Nodes will be less profitable Hacking and Hacknet Nodes will be less profitable
@ -250,9 +252,9 @@ BitNodes["BitNode6"] = new BitNode(
<br /> <br />
<br /> <br />
Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade its Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade its
level up to a maximum of 3. This Source-File allows you to access the NSA's {FactionNames.Bladeburners} Division in other level up to a maximum of 3. This Source-File allows you to access the NSA's {FactionNames.Bladeburners} Division
BitNodes. In addition, this Source-File will raise both the level and experience gain rate of all your combat in other BitNodes. In addition, this Source-File will raise both the level and experience gain rate of all your
stats by: combat stats by:
<br /> <br />
<br /> <br />
Level 1: 8% Level 1: 8%
@ -270,14 +272,15 @@ BitNodes["BitNode7"] = new BitNode(
"More human than humans", "More human than humans",
( (
<> <>
In the middle of the 21st century, you were doing cutting-edge work at {FactionNames.OmniTekIncorporated} as part of the AI In the middle of the 21st century, you were doing cutting-edge work at {FactionNames.OmniTekIncorporated} as part
design team for advanced synthetic androids, or Synthoids for short. You helped achieve a major technological of the AI design team for advanced synthetic androids, or Synthoids for short. You helped achieve a major
breakthrough in the sixth generation of the company's Synthoid design, called MK-VI, by developing a technological breakthrough in the sixth generation of the company's Synthoid design, called MK-VI, by developing a
hyperintelligent AI. Many argue that this was the first sentient AI ever created. This resulted in Synthoid models hyperintelligent AI. Many argue that this was the first sentient AI ever created. This resulted in Synthoid models
that were stronger, faster, and more intelligent than the humans that had created them. that were stronger, faster, and more intelligent than the humans that had created them.
<br /> <br />
<br /> <br />
In this BitNode you will be able to access the {FactionNames.Bladeburners} API, which allows you to access {FactionNames.Bladeburners} In this BitNode you will be able to access the {FactionNames.Bladeburners} API, which allows you to access{" "}
{FactionNames.Bladeburners}
functionality through Netscript. Furthermore: <br /> functionality through Netscript. Furthermore: <br />
<br /> <br />
The rank you gain from {FactionNames.Bladeburners} contracts/operations is reduced by 40% The rank you gain from {FactionNames.Bladeburners} contracts/operations is reduced by 40%
@ -300,8 +303,9 @@ BitNodes["BitNode7"] = new BitNode(
<br /> <br />
<br /> <br />
Destroying this BitNode will give you Source-File 7, or if you already have this Source-File it will upgrade its Destroying this BitNode will give you Source-File 7, or if you already have this Source-File it will upgrade its
level up to a maximum of 3. This Source-File allows you to access the {FactionNames.Bladeburners} Netscript API in other BitNodes. level up to a maximum of 3. This Source-File allows you to access the {FactionNames.Bladeburners} Netscript API in
In addition, this Source-File will increase all of your {FactionNames.Bladeburners} multipliers by: other BitNodes. In addition, this Source-File will increase all of your {FactionNames.Bladeburners} multipliers
by:
<br /> <br />
<br /> <br />
Level 1: 8% Level 1: 8%
@ -364,10 +368,10 @@ BitNodes["BitNode9"] = new BitNode(
"Hacknet Unleashed", "Hacknet Unleashed",
( (
<> <>
When {FactionNames.FulcrumSecretTechnologies} released their open-source Linux distro Chapeau, it quickly became the OS of choice for When {FactionNames.FulcrumSecretTechnologies} released their open-source Linux distro Chapeau, it quickly became
the underground hacking community. Chapeau became especially notorious for powering the Hacknet, a global, the OS of choice for the underground hacking community. Chapeau became especially notorious for powering the
decentralized network used for nefarious purposes. {FactionNames.FulcrumSecretTechnologies} quickly abandoned the project and dissociated Hacknet, a global, decentralized network used for nefarious purposes. {FactionNames.FulcrumSecretTechnologies}{" "}
themselves from it. quickly abandoned the project and dissociated themselves from it.
<br /> <br />
<br /> <br />
This BitNode unlocks the Hacknet Server, an upgraded version of the Hacknet Node. Hacknet Servers generate hashes, This BitNode unlocks the Hacknet Server, an upgraded version of the Hacknet Node. Hacknet Servers generate hashes,
@ -538,8 +542,8 @@ BitNodes["BitNode13"] = new BitNode(
"1 step back, 2 steps forward", "1 step back, 2 steps forward",
( (
<> <>
With the invention of Augmentations in the 2040s a religious group known as the {FactionNames.ChurchOfTheMachineGod} has With the invention of Augmentations in the 2040s a religious group known as the{" "}
rallied far more support than anyone would have hoped. {FactionNames.ChurchOfTheMachineGod} has rallied far more support than anyone would have hoped.
<br /> <br />
<br /> <br />
Their leader, Allison "Mother" Stanek is said to have created her own Augmentation whose power goes beyond any Their leader, Allison "Mother" Stanek is said to have created her own Augmentation whose power goes beyond any
@ -555,7 +559,8 @@ BitNodes["BitNode13"] = new BitNode(
<br /> <br />
<br /> <br />
Destroying this BitNode will give you Source-File 13, or if you already have this Source-File it will upgrade its Destroying this BitNode will give you Source-File 13, or if you already have this Source-File it will upgrade its
level up to a maximum of 3. This Source-File lets the {FactionNames.ChurchOfTheMachineGod} appear in other BitNodes. level up to a maximum of 3. This Source-File lets the {FactionNames.ChurchOfTheMachineGod} appear in other
BitNodes.
<br /> <br />
<br /> <br />
Each level of this Source-File increases the size of Stanek's Gift. Each level of this Source-File increases the size of Stanek's Gift.
@ -624,6 +629,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.PurchasedServerSoftcap = 1.3; BitNodeMultipliers.PurchasedServerSoftcap = 1.3;
BitNodeMultipliers.GangSoftcap = 0.9; BitNodeMultipliers.GangSoftcap = 0.9;
BitNodeMultipliers.WorldDaemonDifficulty = 2; BitNodeMultipliers.WorldDaemonDifficulty = 2;
BitNodeMultipliers.GangUniqueAugs = 0.5;
break; break;
case 4: // The Singularity case 4: // The Singularity
BitNodeMultipliers.ServerMaxMoney = 0.15; BitNodeMultipliers.ServerMaxMoney = 0.15;
@ -642,6 +648,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.StaneksGiftExtraSize = 0; BitNodeMultipliers.StaneksGiftExtraSize = 0;
BitNodeMultipliers.PurchasedServerSoftcap = 1.2; BitNodeMultipliers.PurchasedServerSoftcap = 1.2;
BitNodeMultipliers.WorldDaemonDifficulty = 3; BitNodeMultipliers.WorldDaemonDifficulty = 3;
BitNodeMultipliers.GangUniqueAugs = 0.5;
break; break;
case 5: // Artificial intelligence case 5: // Artificial intelligence
BitNodeMultipliers.ServerMaxMoney = 2; BitNodeMultipliers.ServerMaxMoney = 2;
@ -659,6 +666,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.StaneksGiftExtraSize = 0; BitNodeMultipliers.StaneksGiftExtraSize = 0;
BitNodeMultipliers.PurchasedServerSoftcap = 1.2; BitNodeMultipliers.PurchasedServerSoftcap = 1.2;
BitNodeMultipliers.WorldDaemonDifficulty = 1.5; BitNodeMultipliers.WorldDaemonDifficulty = 1.5;
BitNodeMultipliers.GangUniqueAugs = 0.5;
break; break;
case 6: // Bladeburner case 6: // Bladeburner
BitNodeMultipliers.HackingLevelMultiplier = 0.35; BitNodeMultipliers.HackingLevelMultiplier = 0.35;
@ -679,6 +687,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.7; BitNodeMultipliers.GangSoftcap = 0.7;
BitNodeMultipliers.CorporationSoftCap = 0.9; BitNodeMultipliers.CorporationSoftCap = 0.9;
BitNodeMultipliers.WorldDaemonDifficulty = 2; BitNodeMultipliers.WorldDaemonDifficulty = 2;
BitNodeMultipliers.GangUniqueAugs = 0.2;
break; break;
case 7: // Bladeburner 2079 case 7: // Bladeburner 2079
BitNodeMultipliers.BladeburnerRank = 0.6; BitNodeMultipliers.BladeburnerRank = 0.6;
@ -704,6 +713,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.7; BitNodeMultipliers.GangSoftcap = 0.7;
BitNodeMultipliers.CorporationSoftCap = 0.9; BitNodeMultipliers.CorporationSoftCap = 0.9;
BitNodeMultipliers.WorldDaemonDifficulty = 2; BitNodeMultipliers.WorldDaemonDifficulty = 2;
BitNodeMultipliers.GangUniqueAugs = 0.2;
break; break;
case 8: // Ghost of Wall Street case 8: // Ghost of Wall Street
BitNodeMultipliers.ScriptHackMoney = 0.3; BitNodeMultipliers.ScriptHackMoney = 0.3;
@ -720,6 +730,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.PurchasedServerSoftcap = 4; BitNodeMultipliers.PurchasedServerSoftcap = 4;
BitNodeMultipliers.GangSoftcap = 0; BitNodeMultipliers.GangSoftcap = 0;
BitNodeMultipliers.CorporationSoftCap = 0; BitNodeMultipliers.CorporationSoftCap = 0;
BitNodeMultipliers.GangUniqueAugs = 0;
break; break;
case 9: // Hacktocracy case 9: // Hacktocracy
BitNodeMultipliers.HackingLevelMultiplier = 0.5; BitNodeMultipliers.HackingLevelMultiplier = 0.5;
@ -746,6 +757,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.8; BitNodeMultipliers.GangSoftcap = 0.8;
BitNodeMultipliers.CorporationSoftCap = 0.7; BitNodeMultipliers.CorporationSoftCap = 0.7;
BitNodeMultipliers.WorldDaemonDifficulty = 2; BitNodeMultipliers.WorldDaemonDifficulty = 2;
BitNodeMultipliers.GangUniqueAugs = 0.25;
break; break;
case 10: // Digital Carbon case 10: // Digital Carbon
BitNodeMultipliers.HackingLevelMultiplier = 0.35; BitNodeMultipliers.HackingLevelMultiplier = 0.35;
@ -775,6 +787,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.9; BitNodeMultipliers.GangSoftcap = 0.9;
BitNodeMultipliers.CorporationSoftCap = 0.9; BitNodeMultipliers.CorporationSoftCap = 0.9;
BitNodeMultipliers.WorldDaemonDifficulty = 2; BitNodeMultipliers.WorldDaemonDifficulty = 2;
BitNodeMultipliers.GangUniqueAugs = 0.25;
break; break;
case 11: //The Big Crash case 11: //The Big Crash
BitNodeMultipliers.HackingLevelMultiplier = 0.6; BitNodeMultipliers.HackingLevelMultiplier = 0.6;
@ -796,6 +809,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.PurchasedServerSoftcap = 2; BitNodeMultipliers.PurchasedServerSoftcap = 2;
BitNodeMultipliers.CorporationSoftCap = 0.9; BitNodeMultipliers.CorporationSoftCap = 0.9;
BitNodeMultipliers.WorldDaemonDifficulty = 1.5; BitNodeMultipliers.WorldDaemonDifficulty = 1.5;
BitNodeMultipliers.GangUniqueAugs = 0.75;
break; break;
case 12: { case 12: {
//The Recursion //The Recursion
@ -870,6 +884,8 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.8; BitNodeMultipliers.GangSoftcap = 0.8;
BitNodeMultipliers.CorporationSoftCap = 0.8; BitNodeMultipliers.CorporationSoftCap = 0.8;
BitNodeMultipliers.WorldDaemonDifficulty = inc; BitNodeMultipliers.WorldDaemonDifficulty = inc;
BitNodeMultipliers.GangUniqueAugs = dec;
break; break;
} }
case 13: { case 13: {
@ -912,6 +928,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
BitNodeMultipliers.GangSoftcap = 0.3; BitNodeMultipliers.GangSoftcap = 0.3;
BitNodeMultipliers.CorporationSoftCap = 0.3; BitNodeMultipliers.CorporationSoftCap = 0.3;
BitNodeMultipliers.WorldDaemonDifficulty = 3; BitNodeMultipliers.WorldDaemonDifficulty = 3;
BitNodeMultipliers.GangUniqueAugs = 0.1;
break; break;
} }
default: default:

@ -114,6 +114,11 @@ interface IBitNodeMultipliers {
*/ */
GangSoftcap: number; GangSoftcap: number;
/**
* Percentage of unique augs that the gang has.
*/
GangUniqueAugs: number;
/** /**
* Influences the experienced gained when hacking a server. * Influences the experienced gained when hacking a server.
*/ */
@ -232,6 +237,11 @@ interface IBitNodeMultipliers {
*/ */
WorldDaemonDifficulty: number; WorldDaemonDifficulty: number;
/**
* Influences corporation dividends.
*/
CorporationSoftCap: number;
// Index signature // Index signature
[key: string]: number; [key: string]: number;
} }
@ -295,6 +305,7 @@ export const BitNodeMultipliers: IBitNodeMultipliers = {
BladeburnerSkillCost: 1, BladeburnerSkillCost: 1,
GangSoftcap: 1, GangSoftcap: 1,
GangUniqueAugs: 1,
DaedalusAugsRequirement: 1, DaedalusAugsRequirement: 1,

@ -35,6 +35,7 @@ import { joinFaction } from "../Faction/FactionHelpers";
import { WorkerScript } from "../Netscript/WorkerScript"; import { WorkerScript } from "../Netscript/WorkerScript";
import { FactionNames } from "../Faction/data/FactionNames"; import { FactionNames } from "../Faction/data/FactionNames";
import { BlackOperationNames } from "./data/BlackOperationNames"; import { BlackOperationNames } from "./data/BlackOperationNames";
import { KEY } from "../utils/helpers/keyCodes";
interface BlackOpsAttempt { interface BlackOpsAttempt {
error?: string; error?: string;
@ -793,7 +794,7 @@ export class Bladeburner implements IBladeburner {
if (c === '"') { if (c === '"') {
// Double quotes // Double quotes
const endQuote = command.indexOf('"', i + 1); const endQuote = command.indexOf('"', i + 1);
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === " ")) { if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
args.push(command.substr(i + 1, endQuote - i - 1)); args.push(command.substr(i + 1, endQuote - i - 1));
if (endQuote === command.length - 1) { if (endQuote === command.length - 1) {
start = i = endQuote + 1; start = i = endQuote + 1;
@ -805,7 +806,7 @@ export class Bladeburner implements IBladeburner {
} else if (c === "'") { } else if (c === "'") {
// Single quotes, same thing as above // Single quotes, same thing as above
const endQuote = command.indexOf("'", i + 1); const endQuote = command.indexOf("'", i + 1);
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === " ")) { if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
args.push(command.substr(i + 1, endQuote - i - 1)); args.push(command.substr(i + 1, endQuote - i - 1));
if (endQuote === command.length - 1) { if (endQuote === command.length - 1) {
start = i = endQuote + 1; start = i = endQuote + 1;
@ -814,7 +815,7 @@ export class Bladeburner implements IBladeburner {
} }
continue; continue;
} }
} else if (c === " ") { } else if (c === KEY.SPACE) {
args.push(command.substr(start, i - start)); args.push(command.substr(start, i - start));
start = i + 1; start = i + 1;
} }

@ -89,7 +89,7 @@ export function Console(props: IProps): React.ReactElement {
const consoleHistory = props.bladeburner.consoleHistory; const consoleHistory = props.bladeburner.consoleHistory;
if (event.key === KEY.UPARROW) { if (event.key === KEY.UP_ARROW) {
// up // up
let i = consoleHistoryIndex; let i = consoleHistoryIndex;
const len = consoleHistory.length; const len = consoleHistory.length;
@ -109,7 +109,7 @@ export function Console(props: IProps): React.ReactElement {
setCommand(prevCommand); setCommand(prevCommand);
} }
if (event.key === KEY.DOWNARROW) { if (event.key === KEY.DOWN_ARROW) {
const i = consoleHistoryIndex; const i = consoleHistoryIndex;
const len = consoleHistory.length; const len = consoleHistory.length;
@ -140,14 +140,16 @@ export function Console(props: IProps): React.ReactElement {
return ( return (
<Paper sx={{ p: 1 }}> <Paper sx={{ p: 1 }}>
<Box sx={{ <Box
height: '60vh', sx={{
paddingBottom: '8px', height: "60vh",
display: 'flex', paddingBottom: "8px",
alignItems: 'stretch', display: "flex",
whiteSpace: 'pre-wrap', alignItems: "stretch",
}} whiteSpace: "pre-wrap",
onClick={handleClick}> }}
onClick={handleClick}
>
<Box> <Box>
<Logs entries={[...props.bladeburner.consoleLogs]} /> <Logs entries={[...props.bladeburner.consoleLogs]} />
</Box> </Box>
@ -195,9 +197,7 @@ function Logs({ entries }: ILogProps): React.ReactElement {
return ( return (
<List sx={{ height: "100%", overflow: "auto", p: 1 }} ref={scrollHook}> <List sx={{ height: "100%", overflow: "auto", p: 1 }} ref={scrollHook}>
{entries && entries.map((log: any, i: number) => ( {entries && entries.map((log: any, i: number) => <Line key={i} content={log} />)}
<Line key={i} content={log} />
))}
</List> </List>
); );
} }

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

@ -1,5 +1,5 @@
import { IPlayer } from 'src/PersonObjects/IPlayer'; import { IPlayer } from "src/PersonObjects/IPlayer";
import { MaterialSizes } from './MaterialSizes'; import { MaterialSizes } from "./MaterialSizes";
import { ICorporation } from "./ICorporation"; import { ICorporation } from "./ICorporation";
import { IIndustry } from "./IIndustry"; import { IIndustry } from "./IIndustry";
import { IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData"; import { IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
@ -17,6 +17,7 @@ import { Employee } from "./Employee";
import { IndustryUpgrades } from "./IndustryUpgrades"; import { IndustryUpgrades } from "./IndustryUpgrades";
import { ResearchMap } from "./ResearchMap"; import { ResearchMap } from "./ResearchMap";
import { isRelevantMaterial } from "./ui/Helpers"; import { isRelevantMaterial } from "./ui/Helpers";
import { CityName } from "src/Locations/data/CityNames";
export function NewIndustry(corporation: ICorporation, industry: string, name: string): void { export function NewIndustry(corporation: ICorporation, industry: string, name: string): void {
if (corporation.divisions.find(({ type }) => industry == type)) if (corporation.divisions.find(({ type }) => industry == type))
@ -64,7 +65,7 @@ export function UnlockUpgrade(corporation: ICorporation, upgrade: CorporationUnl
if (corporation.funds < upgrade[1]) { if (corporation.funds < upgrade[1]) {
throw new Error("Insufficient funds"); throw new Error("Insufficient funds");
} }
if(corporation.unlockUpgrades[upgrade[0]] === 1){ if (corporation.unlockUpgrades[upgrade[0]] === 1) {
throw new Error(`You have already unlocked the ${upgrade[2]} upgrade!`); throw new Error(`You have already unlocked the ${upgrade[2]} upgrade!`);
} }
corporation.unlock(upgrade); corporation.unlock(upgrade);
@ -222,15 +223,15 @@ export function SellProduct(product: Product, city: string, amt: string, price:
product.sllman[city][1] = ""; product.sllman[city][1] = "";
} }
} else if (all) { } else if (all) {
for (let i = 0; i < cities.length; ++i) { for (let i = 0; i < cities.length; ++i) {
const tempCity = cities[i]; const tempCity = cities[i];
product.sllman[tempCity][0] = true; product.sllman[tempCity][0] = true;
product.sllman[tempCity][1] = qty; product.sllman[tempCity][1] = qty;
}
} else {
product.sllman[city][0] = true;
product.sllman[city][1] = qty;
} }
} else {
product.sllman[city][0] = true;
product.sllman[city][1] = qty;
}
} }
} }
@ -257,7 +258,7 @@ export function BulkPurchase(corp: ICorporation, warehouse: Warehouse, material:
if (isNaN(amt) || amt < 0) { if (isNaN(amt) || amt < 0) {
throw new Error(`Invalid input amount`); throw new Error(`Invalid input amount`);
} }
if (amt * matSize > maxAmount) { if (amt * matSize <= maxAmount) {
throw new Error(`You do not have enough warehouse size to fit this purchase`); throw new Error(`You do not have enough warehouse size to fit this purchase`);
} }
const cost = amt * material.bCost; const cost = amt * material.bCost;
@ -295,7 +296,7 @@ export function BuyBackShares(corporation: ICorporation, player: IPlayer, numSha
if (numShares > corporation.issuedShares) throw new Error("You don't have that many shares to buy!"); if (numShares > corporation.issuedShares) throw new Error("You don't have that many shares to buy!");
if (!corporation.public) throw new Error("You haven't gone public!"); if (!corporation.public) throw new Error("You haven't gone public!");
const buybackPrice = corporation.sharePrice * 1.1; const buybackPrice = corporation.sharePrice * 1.1;
if (player.money < (numShares * buybackPrice)) throw new Error("You cant afford that many shares!"); if (player.money < numShares * buybackPrice) throw new Error("You cant afford that many shares!");
corporation.numShares += numShares; corporation.numShares += numShares;
corporation.issuedShares -= numShares; corporation.issuedShares -= numShares;
player.loseMoney(numShares * buybackPrice, "corporation"); player.loseMoney(numShares * buybackPrice, "corporation");
@ -404,13 +405,13 @@ export function MakeProduct(
if (corp.funds < designInvest + marketingInvest) { if (corp.funds < designInvest + marketingInvest) {
throw new Error("You don't have enough company funds to make this large of an investment"); throw new Error("You don't have enough company funds to make this large of an investment");
} }
let maxProducts = 3 let maxProducts = 3;
if (division.hasResearch("uPgrade: Capacity.II")) { if (division.hasResearch("uPgrade: Capacity.II")) {
maxProducts = 5 maxProducts = 5;
} else if (division.hasResearch("uPgrade: Capacity.I")) { } else if (division.hasResearch("uPgrade: Capacity.I")) {
maxProducts = 4 maxProducts = 4;
} }
const products = division.products const products = division.products;
if (Object.keys(products).length >= maxProducts) { if (Object.keys(products).length >= maxProducts) {
throw new Error(`You are already at the max products (${maxProducts}) for division: ${division.name}!`); throw new Error(`You are already at the max products (${maxProducts}) for division: ${division.name}!`);
} }
@ -445,7 +446,13 @@ export function Research(division: IIndustry, researchName: string): void {
division.researched[researchName] = true; division.researched[researchName] = true;
} }
export function ExportMaterial(divisionName: string, cityName: string, material: Material, amt: string, division?: Industry): void { export function ExportMaterial(
divisionName: string,
cityName: string,
material: Material,
amt: string,
division?: Industry,
): void {
// Sanitize amt // Sanitize amt
let sanitizedAmt = amt.replace(/\s+/g, "").toUpperCase(); let sanitizedAmt = amt.replace(/\s+/g, "").toUpperCase();
sanitizedAmt = sanitizedAmt.replace(/[^-()\d/*+.MAX]/g, ""); sanitizedAmt = sanitizedAmt.replace(/[^-()\d/*+.MAX]/g, "");

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

@ -10,7 +10,7 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Faction } from "../Faction"; import { Faction } from "../Faction";
import { PurchaseAugmentationsOrderSetting } from "../../Settings/SettingEnums"; import { PurchaseAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import { Settings } from "../../Settings/Settings"; import { Settings } from "../../Settings/Settings";
import { hasAugmentationPrereqs } from "../FactionHelpers"; import { hasAugmentationPrereqs, getFactionAugmentationsFiltered } from "../FactionHelpers";
import { use } from "../../ui/Context"; import { use } from "../../ui/Context";
import { Reputation } from "../../ui/React/Reputation"; import { Reputation } from "../../ui/React/Reputation";
@ -23,7 +23,7 @@ import Typography from "@mui/material/Typography";
import Tooltip from "@mui/material/Tooltip"; import Tooltip from "@mui/material/Tooltip";
import TableBody from "@mui/material/TableBody"; import TableBody from "@mui/material/TableBody";
import Table from "@mui/material/Table"; import Table from "@mui/material/Table";
import { CONSTANTS } from "../../Constants"; import { getGenericAugmentationPriceMultiplier } from "../../Augmentation/AugmentationHelpers";
type IProps = { type IProps = {
faction: Faction; faction: Faction;
@ -42,25 +42,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
} }
function getAugs(): string[] { function getAugs(): string[] {
if (isPlayersGang) { return getFactionAugmentationsFiltered(player, props.faction);
let augs = Object.values(Augmentations);
// Remove blacklisted augs.
const blacklist = [AugmentationNames.NeuroFluxGovernor, AugmentationNames.TheRedPill];
augs = augs.filter((a) => !blacklist.includes(a.name));
// Remove special augs.
augs = augs.filter((a) => !a.isSpecial);
// Remove faction-unique augs outside BN2. (But keep the one for this faction.)
if (player.bitNodeN !== 2) {
augs = augs.filter((a) => a.factions.length > 1 || props.faction.augmentations.includes(a.name));
}
return augs.map((a) => a.name);
} else {
return props.faction.augmentations.slice();
}
} }
function getAugsSorted(): string[] { function getAugsSorted(): string[] {
@ -184,10 +166,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
</> </>
); );
} }
const mult = Math.pow(
CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][player.sourceFileLvl(11)],
player.queuedAugmentations.length,
);
return ( return (
<> <>
<Button onClick={props.routeToMainPage}>Back</Button> <Button onClick={props.routeToMainPage}>Back</Button>
@ -208,7 +187,9 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
</Typography> </Typography>
} }
> >
<Typography>Price multiplier: x {numeralWrapper.formatMultiplier(mult)}</Typography> <Typography>
Price multiplier: x {numeralWrapper.formatMultiplier(getGenericAugmentationPriceMultiplier())}
</Typography>
</Tooltip> </Tooltip>
</Box> </Box>
<Button onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Cost)}>Sort by Cost</Button> <Button onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Cost)}>Sort by Cost</Button>

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

@ -227,7 +227,6 @@ export class Gang implements IGang {
AllGangs[thisGang].territory += territoryGain; AllGangs[thisGang].territory += territoryGain;
if (AllGangs[thisGang].territory > 0.999) AllGangs[thisGang].territory = 1; if (AllGangs[thisGang].territory > 0.999) AllGangs[thisGang].territory = 1;
AllGangs[otherGang].territory -= territoryGain; AllGangs[otherGang].territory -= territoryGain;
if (AllGangs[thisGang].territory) AllGangs[thisGang].territory = 0;
if (thisGang === gangName) { if (thisGang === gangName) {
this.clash(true); // Player won this.clash(true); // Player won
AllGangs[otherGang].power *= 1 / 1.01; AllGangs[otherGang].power *= 1 / 1.01;

@ -7,6 +7,7 @@ import { random } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { BlinkingCursor } from "./BlinkingCursor"; import { BlinkingCursor } from "./BlinkingCursor";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -36,7 +37,7 @@ export function BackwardGame(props: IMinigameProps): React.ReactElement {
function press(this: Document, event: KeyboardEvent): void { function press(this: Document, event: KeyboardEvent): void {
event.preventDefault(); event.preventDefault();
if (event.key === "Backspace") return; if (event.key === KEY.BACKSPACE) return;
const nextGuess = guess + event.key.toUpperCase(); const nextGuess = guess + event.key.toUpperCase();
if (!answer.startsWith(nextGuess)) props.onFailure(); if (!answer.startsWith(nextGuess)) props.onFailure();
else if (answer === nextGuess) props.onSuccess(); else if (answer === nextGuess) props.onSuccess();

@ -7,6 +7,7 @@ import { random } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { BlinkingCursor } from "./BlinkingCursor"; import { BlinkingCursor } from "./BlinkingCursor";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -29,28 +30,29 @@ const difficulties: {
function generateLeftSide(difficulty: Difficulty): string { function generateLeftSide(difficulty: Difficulty): string {
let str = ""; let str = "";
const options = [KEY.OPEN_BRACKET, KEY.LESS_THAN, KEY.OPEN_PARENTHESIS, KEY.OPEN_BRACE];
const length = random(difficulty.min, difficulty.max); const length = random(difficulty.min, difficulty.max);
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
str += ["[", "<", "(", "{"][Math.floor(Math.random() * 4)]; str += options[Math.floor(Math.random() * 4)];
} }
return str; return str;
} }
function getChar(event: KeyboardEvent): string { function getChar(event: KeyboardEvent): string {
if (event.key === ")") return ")"; if (event.key === KEY.CLOSE_PARENTHESIS) return KEY.CLOSE_PARENTHESIS;
if (event.key === "]") return "]"; if (event.key === KEY.CLOSE_BRACKET) return KEY.CLOSE_BRACKET;
if (event.key === "}") return "}"; if (event.key === KEY.CLOSE_BRACE) return KEY.CLOSE_BRACE;
if (event.key === ">") return ">"; if (event.key === KEY.GREATER_THAN) return KEY.GREATER_THAN;
return ""; return "";
} }
function match(left: string, right: string): boolean { function match(left: string, right: string): boolean {
return ( return (
(left === "[" && right === "]") || (left === KEY.OPEN_BRACKET && right === KEY.CLOSE_BRACKET) ||
(left === "<" && right === ">") || (left === KEY.LESS_THAN && right === KEY.GREATER_THAN) ||
(left === "(" && right === ")") || (left === KEY.OPEN_PARENTHESIS && right === KEY.CLOSE_PARENTHESIS) ||
(left === "{" && right === "}") (left === KEY.OPEN_BRACE && right === KEY.CLOSE_BRACE)
); );
} }

@ -5,6 +5,8 @@ import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
import { downArrowSymbol, upArrowSymbol } from "../utils";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -34,15 +36,15 @@ export function BribeGame(props: IMinigameProps): React.ReactElement {
function press(this: Document, event: KeyboardEvent): void { function press(this: Document, event: KeyboardEvent): void {
event.preventDefault(); event.preventDefault();
const k = event.key; const k = event.key;
if (k === " ") { if (k === KEY.SPACE) {
if (positive.includes(choices[index])) props.onSuccess(); if (positive.includes(choices[index])) props.onSuccess();
else props.onFailure(); else props.onFailure();
return; return;
} }
let newIndex = index; let newIndex = index;
if (["ArrowUp", "w", "ArrowRight", "d"].includes(k)) newIndex++; if ([KEY.UP_ARROW, KEY.W, KEY.RIGHT_ARROW, KEY.D].map((key) => key as string).includes(k)) newIndex++;
if (["ArrowDown", "s", "ArrowLeft", "a"].includes(k)) newIndex--; if ([KEY.DOWN_ARROW, KEY.S, KEY.LEFT_ARROW, KEY.A].map((key) => key as string).includes(k)) newIndex--;
while (newIndex < 0) newIndex += choices.length; while (newIndex < 0) newIndex += choices.length;
while (newIndex > choices.length - 1) newIndex -= choices.length; while (newIndex > choices.length - 1) newIndex -= choices.length;
setIndex(newIndex); setIndex(newIndex);
@ -57,13 +59,13 @@ export function BribeGame(props: IMinigameProps): React.ReactElement {
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="h5" color="primary"> <Typography variant="h5" color="primary">
{upArrowSymbol}
</Typography> </Typography>
<Typography variant="h5" color="primary"> <Typography variant="h5" color="primary">
{choices[index]} {choices[index]}
</Typography> </Typography>
<Typography variant="h5" color="primary"> <Typography variant="h5" color="primary">
{downArrowSymbol}
</Typography> </Typography>
</Grid> </Grid>
</Grid> </Grid>

@ -3,7 +3,7 @@ import Grid from "@mui/material/Grid";
import { IMinigameProps } from "./IMinigameProps"; import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler"; import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { random, getArrow } from "../utils"; import { random, getArrow, rightArrowSymbol, leftArrowSymbol, upArrowSymbol, downArrowSymbol } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
@ -56,7 +56,7 @@ export function CheatCodeGame(props: IMinigameProps): React.ReactElement {
} }
function generateCode(difficulty: Difficulty): string { function generateCode(difficulty: Difficulty): string {
const arrows = ["←", "→", "↑", "↓"]; const arrows = [leftArrowSymbol, rightArrowSymbol, upArrowSymbol, downArrowSymbol];
let code = ""; let code = "";
for (let i = 0; i < random(difficulty.min, difficulty.max); i++) { for (let i = 0; i < random(difficulty.min, difficulty.max); i++) {
let arrow = arrows[Math.floor(4 * Math.random())]; let arrow = arrows[Math.floor(4 * Math.random())];

@ -4,8 +4,9 @@ import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler"; import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { getArrow } from "../utils"; import { downArrowSymbol, getArrow, leftArrowSymbol, rightArrowSymbol, upArrowSymbol } from "../utils";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -41,16 +42,16 @@ export function Cyberpunk2077Game(props: IMinigameProps): React.ReactElement {
const move = [0, 0]; const move = [0, 0];
const arrow = getArrow(event); const arrow = getArrow(event);
switch (arrow) { switch (arrow) {
case "↑": case upArrowSymbol:
move[1]--; move[1]--;
break; break;
case "←": case leftArrowSymbol:
move[0]--; move[0]--;
break; break;
case "↓": case downArrowSymbol:
move[1]++; move[1]++;
break; break;
case "→": case rightArrowSymbol:
move[0]++; move[0]++;
break; break;
} }
@ -59,7 +60,7 @@ export function Cyberpunk2077Game(props: IMinigameProps): React.ReactElement {
next[1] = (next[1] + grid.length) % grid.length; next[1] = (next[1] + grid.length) % grid.length;
setPos(next); setPos(next);
if (event.key === " ") { if (event.key === KEY.SPACE) {
const selected = grid[pos[1]][pos[0]]; const selected = grid[pos[1]][pos[0]];
const expected = answer[index]; const expected = answer[index];
if (selected !== expected) { if (selected !== expected) {

@ -4,8 +4,9 @@ import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler"; import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { getArrow } from "../utils"; import { downArrowSymbol, getArrow, leftArrowSymbol, rightArrowSymbol, upArrowSymbol } from "../utils";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -42,16 +43,16 @@ export function MinesweeperGame(props: IMinigameProps): React.ReactElement {
const move = [0, 0]; const move = [0, 0];
const arrow = getArrow(event); const arrow = getArrow(event);
switch (arrow) { switch (arrow) {
case "↑": case upArrowSymbol:
move[1]--; move[1]--;
break; break;
case "←": case leftArrowSymbol:
move[0]--; move[0]--;
break; break;
case "↓": case downArrowSymbol:
move[1]++; move[1]++;
break; break;
case "→": case rightArrowSymbol:
move[0]++; move[0]++;
break; break;
} }
@ -60,7 +61,7 @@ export function MinesweeperGame(props: IMinigameProps): React.ReactElement {
next[1] = (next[1] + minefield.length) % minefield.length; next[1] = (next[1] + minefield.length) % minefield.length;
setPos(next); setPos(next);
if (event.key == " ") { if (event.key == KEY.SPACE) {
if (!minefield[pos[1]][pos[0]]) { if (!minefield[pos[1]][pos[0]]) {
props.onFailure(); props.onFailure();
return; return;

@ -5,6 +5,7 @@ import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -30,7 +31,7 @@ export function SlashGame(props: IMinigameProps): React.ReactElement {
function press(this: Document, event: KeyboardEvent): void { function press(this: Document, event: KeyboardEvent): void {
event.preventDefault(); event.preventDefault();
if (event.key !== " ") return; if (event.key !== KEY.SPACE) return;
if (phase !== 2) { if (phase !== 2) {
props.onFailure(); props.onFailure();
} else { } else {

@ -6,6 +6,7 @@ import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { random } from "../utils"; import { random } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -27,7 +28,7 @@ const difficulties: {
Impossible: { timer: 4000, wiresmin: 9, wiresmax: 9, rules: 4 }, Impossible: { timer: 4000, wiresmin: 9, wiresmax: 9, rules: 4 },
}; };
const types = ["|", ".", "/", "-", "█", "#"]; const types = [KEY.PIPE, KEY.DOT, KEY.FORWARD_SLASH, KEY.HYPHEN, "█", KEY.HASH];
const colors = ["red", "#FFC107", "blue", "white"]; const colors = ["red", "#FFC107", "blue", "white"];
@ -61,6 +62,10 @@ export function WireCuttingGame(props: IMinigameProps): React.ReactElement {
const [cutWires, setCutWires] = useState(new Array(wires.length).fill(false)); const [cutWires, setCutWires] = useState(new Array(wires.length).fill(false));
const [questions] = useState(generateQuestion(wires, difficulty)); const [questions] = useState(generateQuestion(wires, difficulty));
function checkWire(wireNum: number): boolean {
return !questions.some((q) => q.shouldCut(wires[wireNum - 1], wireNum - 1));
}
function press(this: Document, event: KeyboardEvent): void { function press(this: Document, event: KeyboardEvent): void {
event.preventDefault(); event.preventDefault();
const wireNum = parseInt(event.key); const wireNum = parseInt(event.key);
@ -69,7 +74,7 @@ export function WireCuttingGame(props: IMinigameProps): React.ReactElement {
setCutWires((old) => { setCutWires((old) => {
const next = [...old]; const next = [...old];
next[wireNum - 1] = true; next[wireNum - 1] = true;
if (!questions.some((q) => q.shouldCut(wires[wireNum - 1], wireNum - 1))) { if (checkWire(wireNum)) {
props.onFailure(); props.onFailure();
} }

@ -1,21 +1,46 @@
import { KEY } from "../utils/helpers/keyCodes";
export function random(min: number, max: number): number { export function random(min: number, max: number): number {
return Math.random() * (max - min) + min; return Math.random() * (max - min) + min;
} }
export const upArrowSymbol = "↑";
export const downArrowSymbol = "↓";
export const leftArrowSymbol = "←";
export const rightArrowSymbol = "→";
export function getArrow(event: KeyboardEvent): string { export function getArrow(event: KeyboardEvent): string {
switch (event.key) { switch (event.key) {
case "ArrowUp": case KEY.UP_ARROW:
case "w": case KEY.W:
return "↑"; return upArrowSymbol;
case "ArrowLeft": case KEY.LEFT_ARROW:
case "a": case KEY.A:
return "←"; return leftArrowSymbol;
case "ArrowDown": case KEY.DOWN_ARROW:
case "s": case KEY.S:
return "↓"; return downArrowSymbol;
case "ArrowRight": case KEY.RIGHT_ARROW:
case "d": case KEY.D:
return "→"; return rightArrowSymbol;
}
return "";
}
export function getInverseArrow(event: KeyboardEvent): string {
switch (event.key) {
case KEY.DOWN_ARROW:
case KEY.S:
return upArrowSymbol;
case KEY.RIGHT_ARROW:
case KEY.D:
return leftArrowSymbol;
case KEY.UP_ARROW:
case KEY.W:
return downArrowSymbol;
case KEY.LEFT_ARROW:
case KEY.A:
return rightArrowSymbol;
} }
return ""; return "";
} }

@ -136,6 +136,7 @@ export const RamCosts: IMap<any> = {
kill: RamCostConstants.ScriptKillRamCost, kill: RamCostConstants.ScriptKillRamCost,
killall: RamCostConstants.ScriptKillRamCost, killall: RamCostConstants.ScriptKillRamCost,
exit: 0, exit: 0,
atExit: 0,
scp: RamCostConstants.ScriptScpRamCost, scp: RamCostConstants.ScriptScpRamCost,
ls: RamCostConstants.ScriptScanRamCost, ls: RamCostConstants.ScriptScanRamCost,
ps: RamCostConstants.ScriptScanRamCost, ps: RamCostConstants.ScriptScanRamCost,
@ -364,16 +365,16 @@ export const RamCosts: IMap<any> = {
}, },
stanek: { stanek: {
width: RamCostConstants.ScriptStanekWidth, giftWidth: RamCostConstants.ScriptStanekWidth,
height: RamCostConstants.ScriptStanekHeight, giftHeight: RamCostConstants.ScriptStanekHeight,
charge: RamCostConstants.ScriptStanekCharge, chargeFragment: RamCostConstants.ScriptStanekCharge,
fragmentDefinitions: RamCostConstants.ScriptStanekFragmentDefinitions, fragmentDefinitions: RamCostConstants.ScriptStanekFragmentDefinitions,
activeFragments: RamCostConstants.ScriptStanekPlacedFragments, activeFragments: RamCostConstants.ScriptStanekPlacedFragments,
clear: RamCostConstants.ScriptStanekClear, clearGift: RamCostConstants.ScriptStanekClear,
canPlace: RamCostConstants.ScriptStanekCanPlace, canPlaceFragment: RamCostConstants.ScriptStanekCanPlace,
place: RamCostConstants.ScriptStanekPlace, placeFragment: RamCostConstants.ScriptStanekPlace,
get: RamCostConstants.ScriptStanekFragmentAt, getFragment: RamCostConstants.ScriptStanekFragmentAt,
remove: RamCostConstants.ScriptStanekDeleteAt, removeFragment: RamCostConstants.ScriptStanekDeleteAt,
}, },
ui: { ui: {
@ -387,8 +388,8 @@ export const RamCosts: IMap<any> = {
}, },
grafting: { grafting: {
getAugmentationCraftPrice: 3.75, getAugmentationGraftPrice: 3.75,
getAugmentationCraftTime: 3.75, getAugmentationGraftTime: 3.75,
graftAugmentation: 7.5, graftAugmentation: 7.5,
}, },

@ -80,6 +80,13 @@ import {
Bladeburner as IBladeburner, Bladeburner as IBladeburner,
Stanek as IStanek, Stanek as IStanek,
SourceFileLvl, SourceFileLvl,
BasicHGWOptions,
ProcessInfo,
HackingMultipliers,
HacknetMultipliers,
BitNodeMultipliers as IBNMults,
Server as IServerDef,
RunningScript as IRunningScriptDef,
} from "./ScriptEditor/NetscriptDefinitions"; } from "./ScriptEditor/NetscriptDefinitions";
import { NetscriptSingularity } from "./NetscriptFunctions/Singularity"; import { NetscriptSingularity } from "./NetscriptFunctions/Singularity";
@ -91,6 +98,7 @@ import { SnackbarEvents } from "./ui/React/Snackbar";
import { Flags } from "./NetscriptFunctions/Flags"; import { Flags } from "./NetscriptFunctions/Flags";
import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence";
import { CalculateShareMult, StartSharing } from "./NetworkShare/Share"; import { CalculateShareMult, StartSharing } from "./NetworkShare/Share";
import { CityName } from "./Locations/data/CityNames";
interface NS extends INS { interface NS extends INS {
[key: string]: any; [key: string]: any;
@ -162,9 +170,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
* is not specified. * is not specified.
*/ */
const getRunningScript = function ( const getRunningScript = function (
fn: any, fn: string,
hostname: any, hostname: string,
callingFnName: any, callingFnName: string,
scriptArgs: any, scriptArgs: any,
): RunningScript | null { ): RunningScript | null {
if (typeof callingFnName !== "string" || callingFnName === "") { if (typeof callingFnName !== "string" || callingFnName === "") {
@ -193,7 +201,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return workerScript.scriptRef; return workerScript.scriptRef;
}; };
const getRunningScriptByPid = function (pid: any, callingFnName: any): RunningScript | null { const getRunningScriptByPid = function (pid: number, callingFnName: string): RunningScript | null {
if (typeof callingFnName !== "string" || callingFnName === "") { if (typeof callingFnName !== "string" || callingFnName === "") {
callingFnName = "getRunningScriptgetRunningScriptByPid"; callingFnName = "getRunningScriptgetRunningScriptByPid";
} }
@ -213,7 +221,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
* @param {any[]} scriptArgs - Running script's arguments * @param {any[]} scriptArgs - Running script's arguments
* @returns {string} Error message to print to logs * @returns {string} Error message to print to logs
*/ */
const getCannotFindRunningScriptErrorMessage = function (fn: any, hostname: any, scriptArgs: any): string { const getCannotFindRunningScriptErrorMessage = function (fn: string, hostname: string, scriptArgs: any): string {
if (!Array.isArray(scriptArgs)) { if (!Array.isArray(scriptArgs)) {
scriptArgs = []; scriptArgs = [];
} }
@ -228,7 +236,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
* @param {string} callingFn - Name of calling function. For logging purposes * @param {string} callingFn - Name of calling function. For logging purposes
* @returns {boolean} True if the server is a Hacknet Server, false otherwise * @returns {boolean} True if the server is a Hacknet Server, false otherwise
*/ */
const failOnHacknetServer = function (server: any, callingFn: any = ""): boolean { const failOnHacknetServer = function (server: BaseServer, callingFn = ""): boolean {
if (server instanceof HacknetServer) { if (server instanceof HacknetServer) {
workerScript.log(callingFn, () => `Does not work on Hacknet Servers`); workerScript.log(callingFn, () => `Does not work on Hacknet Servers`);
return true; return true;
@ -316,7 +324,11 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
}; };
const hack = function (hostname: any, manual: any, { threads: requestedThreads, stock }: any = {}): Promise<number> { const hack = function (
hostname: string,
manual: boolean,
{ threads: requestedThreads, stock }: any = {},
): Promise<number> {
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("hack", "Takes 1 argument."); throw makeRuntimeErrorMsg("hack", "Takes 1 argument.");
} }
@ -429,25 +441,32 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
string: (funcName: string, argName: string, v: unknown): string => { string: (funcName: string, argName: string, v: unknown): string => {
if (typeof v === "string") return v; if (typeof v === "string") return v;
if (typeof v === "number") return v + ""; // cast to string; if (typeof v === "number") return v + ""; // cast to string;
throw makeRuntimeErrorMsg(funcName, `${argName} should be a string`); throw makeRuntimeErrorMsg(funcName, `${argName} should be a string.`);
}, },
number: (funcName: string, argName: string, v: unknown): number => { number: (funcName: string, argName: string, v: unknown): number => {
if (typeof v === "string") { if (typeof v === "string") {
const x = parseFloat(v); const x = parseFloat(v);
if (!isNaN(x)) return x; // otherwise it wasn't even a string representing a number. if (!isNaN(x)) return x; // otherwise it wasn't even a string representing a number.
} else if (typeof v === "number") { } else if (typeof v === "number") {
if (isNaN(v)) throw makeRuntimeErrorMsg(funcName, `${argName} is NaN`); if (isNaN(v)) throw makeRuntimeErrorMsg(funcName, `${argName} is NaN.`);
return v; return v;
} }
throw makeRuntimeErrorMsg(funcName, `${argName} should be a number`); throw makeRuntimeErrorMsg(funcName, `${argName} should be a number.`);
}, },
boolean: (v: unknown): boolean => { boolean: (v: unknown): boolean => {
return !!v; // Just convert it to boolean. return !!v; // Just convert it to boolean.
}, },
city: (funcName: string, argName: string, v: unknown): CityName => {
if (typeof v !== "string") throw makeRuntimeErrorMsg(funcName, `${argName} should be a city name.`);
const s = v as CityName;
if (!Object.values(CityName).includes(s))
throw makeRuntimeErrorMsg(funcName, `${argName} should be a city name.`);
return s;
},
getServer: safeGetServer, getServer: safeGetServer,
checkSingularityAccess: checkSingularityAccess, checkSingularityAccess: checkSingularityAccess,
hack: hack, hack: hack,
getValidPort: (funcName: string, port: any): IPort => { getValidPort: (funcName: string, port: number): IPort => {
if (isNaN(port)) { if (isNaN(port)) {
throw makeRuntimeErrorMsg( throw makeRuntimeErrorMsg(
funcName, funcName,
@ -486,6 +505,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
const base: INS = { const base: INS = {
...singularity, ...singularity,
singularity: singularity,
gang: gang, gang: gang,
bladeburner: bladeburner, bladeburner: bladeburner,
codingcontract: codingcontract, codingcontract: codingcontract,
@ -500,7 +520,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
hacknet: hacknet, hacknet: hacknet,
sprintf: sprintf, sprintf: sprintf,
vsprintf: vsprintf, vsprintf: vsprintf,
scan: function (hostname: any = workerScript.hostname): any { scan: function (_hostname: unknown = workerScript.hostname): string[] {
const hostname = helper.string("scan", "hostname", _hostname);
updateDynamicRam("scan", getRamCost(Player, "scan")); updateDynamicRam("scan", getRamCost(Player, "scan"));
const server = safeGetServer(hostname, "scan"); const server = safeGetServer(hostname, "scan");
const out = []; const out = [];
@ -514,11 +535,14 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.log("scan", () => `returned ${server.serversOnNetwork.length} connections for ${server.hostname}`); workerScript.log("scan", () => `returned ${server.serversOnNetwork.length} connections for ${server.hostname}`);
return out; return out;
}, },
hack: function (hostname: any, { threads: requestedThreads, stock }: any = {}): any { hack: function (_hostname: unknown, { threads: requestedThreads, stock }: BasicHGWOptions = {}): Promise<number> {
const hostname = helper.string("hack", "hostname", _hostname);
updateDynamicRam("hack", getRamCost(Player, "hack")); updateDynamicRam("hack", getRamCost(Player, "hack"));
return hack(hostname, false, { threads: requestedThreads, stock: stock }); return hack(hostname, false, { threads: requestedThreads, stock: stock });
}, },
hackAnalyzeThreads: function (hostname: any, hackAmount: any): any { hackAnalyzeThreads: function (_hostname: unknown, _hackAmount: unknown): number {
const hostname = helper.string("hackAnalyzeThreads", "hostname", _hostname);
const hackAmount = helper.number("hackAnalyzeThreads", "hackAmount", _hackAmount);
updateDynamicRam("hackAnalyzeThreads", getRamCost(Player, "hackAnalyzeThreads")); updateDynamicRam("hackAnalyzeThreads", getRamCost(Player, "hackAnalyzeThreads"));
// Check argument validity // Check argument validity
@ -548,43 +572,48 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return hackAmount / Math.floor(server.moneyAvailable * percentHacked); return hackAmount / Math.floor(server.moneyAvailable * percentHacked);
}, },
hackAnalyze: function (hostname: any): any { hackAnalyze: function (_hostname: unknown): number {
const hostname = helper.string("hackAnalyze", "hostname", _hostname);
updateDynamicRam("hackAnalyze", getRamCost(Player, "hackAnalyze")); updateDynamicRam("hackAnalyze", getRamCost(Player, "hackAnalyze"));
const server = safeGetServer(hostname, "hackAnalyze"); const server = safeGetServer(hostname, "hackAnalyze");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
workerScript.log("hackAnalyze", () => "Cannot be executed on this server."); workerScript.log("hackAnalyze", () => "Cannot be executed on this server.");
return false; return 0;
} }
return calculatePercentMoneyHacked(server, Player); return calculatePercentMoneyHacked(server, Player);
}, },
hackAnalyzeSecurity: function (threads: any): number { hackAnalyzeSecurity: function (_threads: unknown): number {
const threads = helper.number("hackAnalyzeSecurity", "threads", _threads);
updateDynamicRam("hackAnalyzeSecurity", getRamCost(Player, "hackAnalyzeSecurity")); updateDynamicRam("hackAnalyzeSecurity", getRamCost(Player, "hackAnalyzeSecurity"));
return CONSTANTS.ServerFortifyAmount * threads; return CONSTANTS.ServerFortifyAmount * threads;
}, },
hackAnalyzeChance: function (hostname: any): any { hackAnalyzeChance: function (_hostname: unknown): number {
const hostname = helper.string("hackAnalyzeChance", "hostname", _hostname);
updateDynamicRam("hackAnalyzeChance", getRamCost(Player, "hackAnalyzeChance")); updateDynamicRam("hackAnalyzeChance", getRamCost(Player, "hackAnalyzeChance"));
const server = safeGetServer(hostname, "hackAnalyzeChance"); const server = safeGetServer(hostname, "hackAnalyzeChance");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
workerScript.log("hackAnalyzeChance", () => "Cannot be executed on this server."); workerScript.log("hackAnalyzeChance", () => "Cannot be executed on this server.");
return false; return 0;
} }
return calculateHackingChance(server, Player); return calculateHackingChance(server, Player);
}, },
sleep: function (time: any): any { sleep: async function (_time: unknown = 0): Promise<void> {
const time = helper.number("sleep", "time", _time);
updateDynamicRam("sleep", getRamCost(Player, "sleep")); updateDynamicRam("sleep", getRamCost(Player, "sleep"));
if (time === undefined) { if (time === undefined) {
throw makeRuntimeErrorMsg("sleep", "Takes 1 argument."); throw makeRuntimeErrorMsg("sleep", "Takes 1 argument.");
} }
workerScript.log("sleep", () => `Sleeping for ${time} milliseconds`); workerScript.log("sleep", () => `Sleeping for ${time} milliseconds`);
return netscriptDelay(time, workerScript).then(function () { return netscriptDelay(time, workerScript).then(function () {
return Promise.resolve(true); return Promise.resolve();
}); });
}, },
asleep: function (time: any): any { asleep: function (_time: unknown = 0): Promise<void> {
const time = helper.number("asleep", "time", _time);
updateDynamicRam("asleep", getRamCost(Player, "asleep")); updateDynamicRam("asleep", getRamCost(Player, "asleep"));
if (time === undefined) { if (time === undefined) {
throw makeRuntimeErrorMsg("asleep", "Takes 1 argument."); throw makeRuntimeErrorMsg("asleep", "Takes 1 argument.");
@ -592,16 +621,24 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.log("asleep", () => `Sleeping for ${time} milliseconds`); workerScript.log("asleep", () => `Sleeping for ${time} milliseconds`);
return new Promise((resolve) => setTimeout(resolve, time)); return new Promise((resolve) => setTimeout(resolve, time));
}, },
grow: function (hostname: any, { threads: requestedThreads, stock }: any = {}): any { grow: async function (
_hostname: unknown,
{ threads: requestedThreads, stock }: BasicHGWOptions = {},
): Promise<number> {
const hostname = helper.string("grow", "hostname", _hostname);
updateDynamicRam("grow", getRamCost(Player, "grow")); updateDynamicRam("grow", getRamCost(Player, "grow"));
const threads = resolveNetscriptRequestedThreads(workerScript, "grow", requestedThreads); const threads = resolveNetscriptRequestedThreads(
workerScript,
"grow",
requestedThreads ?? workerScript.scriptRef.threads,
);
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("grow", "Takes 1 argument."); throw makeRuntimeErrorMsg("grow", "Takes 1 argument.");
} }
const server = safeGetServer(hostname, "grow"); const server = safeGetServer(hostname, "grow");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
workerScript.log("grow", () => "Cannot be executed on this server."); workerScript.log("grow", () => "Cannot be executed on this server.");
return false; return Promise.resolve(0);
} }
const host = GetServer(workerScript.hostname); const host = GetServer(workerScript.hostname);
@ -647,14 +684,17 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return Promise.resolve(moneyAfter / moneyBefore); return Promise.resolve(moneyAfter / moneyBefore);
}); });
}, },
growthAnalyze: function (hostname: any, growth: any, cores: any = 1): any { growthAnalyze: function (_hostname: unknown, _growth: unknown, _cores: unknown = 1): number {
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")); updateDynamicRam("growthAnalyze", getRamCost(Player, "growthAnalyze"));
// Check argument validity // Check argument validity
const server = safeGetServer(hostname, "growthAnalyze"); const server = safeGetServer(hostname, "growthAnalyze");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
workerScript.log("growthAnalyze", () => "Cannot be executed on this server."); workerScript.log("growthAnalyze", () => "Cannot be executed on this server.");
return false; return 0;
} }
if (typeof growth !== "number" || isNaN(growth) || growth < 1 || !isFinite(growth)) { if (typeof growth !== "number" || isNaN(growth) || growth < 1 || !isFinite(growth)) {
throw makeRuntimeErrorMsg("growthAnalyze", `Invalid argument: growth must be numeric and >= 1, is ${growth}.`); throw makeRuntimeErrorMsg("growthAnalyze", `Invalid argument: growth must be numeric and >= 1, is ${growth}.`);
@ -662,20 +702,26 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return numCycleForGrowth(server, Number(growth), Player, cores); return numCycleForGrowth(server, Number(growth), Player, cores);
}, },
growthAnalyzeSecurity: function (threads: any): number { growthAnalyzeSecurity: function (_threads: unknown): number {
const threads = helper.number("growthAnalyzeSecurity", "threads", _threads);
updateDynamicRam("growthAnalyzeSecurity", getRamCost(Player, "growthAnalyzeSecurity")); updateDynamicRam("growthAnalyzeSecurity", getRamCost(Player, "growthAnalyzeSecurity"));
return 2 * CONSTANTS.ServerFortifyAmount * threads; return 2 * CONSTANTS.ServerFortifyAmount * threads;
}, },
weaken: function (hostname: any, { threads: requestedThreads }: any = {}): any { weaken: async function (_hostname: unknown, { threads: requestedThreads }: BasicHGWOptions = {}): Promise<number> {
const hostname = helper.string("weaken", "hostname", _hostname);
updateDynamicRam("weaken", getRamCost(Player, "weaken")); updateDynamicRam("weaken", getRamCost(Player, "weaken"));
const threads = resolveNetscriptRequestedThreads(workerScript, "weaken", requestedThreads); const threads = resolveNetscriptRequestedThreads(
workerScript,
"weaken",
requestedThreads ?? workerScript.scriptRef.threads,
);
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("weaken", "Takes 1 argument."); throw makeRuntimeErrorMsg("weaken", "Takes 1 argument.");
} }
const server = safeGetServer(hostname, "weaken"); const server = safeGetServer(hostname, "weaken");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
workerScript.log("weaken", () => "Cannot be executed on this server."); workerScript.log("weaken", () => "Cannot be executed on this server.");
return false; return Promise.resolve(0);
} }
// No root access or skill level too low // No root access or skill level too low
@ -715,12 +761,14 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return Promise.resolve(CONSTANTS.ServerWeakenAmount * threads * coreBonus); return Promise.resolve(CONSTANTS.ServerWeakenAmount * threads * coreBonus);
}); });
}, },
weakenAnalyze: function (threads: any, cores: any = 1): number { weakenAnalyze: function (_threads: unknown, _cores: unknown = 1): number {
const threads = helper.number("weakenAnalyze", "threads", _threads);
const cores = helper.number("weakenAnalyze", "cores", _cores);
updateDynamicRam("weakenAnalyze", getRamCost(Player, "weakenAnalyze")); updateDynamicRam("weakenAnalyze", getRamCost(Player, "weakenAnalyze"));
const coreBonus = 1 + (cores - 1) / 16; const coreBonus = 1 + (cores - 1) / 16;
return CONSTANTS.ServerWeakenAmount * threads * coreBonus * BitNodeMultipliers.ServerWeakenRate; return CONSTANTS.ServerWeakenAmount * threads * coreBonus * BitNodeMultipliers.ServerWeakenRate;
}, },
share: function (): Promise<void> { share: async function (): Promise<void> {
updateDynamicRam("share", getRamCost(Player, "share")); updateDynamicRam("share", getRamCost(Player, "share"));
workerScript.log("share", () => "Sharing this computer."); workerScript.log("share", () => "Sharing this computer.");
const end = StartSharing(workerScript.scriptRef.threads * calculateIntelligenceBonus(Player.intelligence, 2)); const end = StartSharing(workerScript.scriptRef.threads * calculateIntelligenceBonus(Player.intelligence, 2));
@ -740,7 +788,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
workerScript.print(argsToString(args)); workerScript.print(argsToString(args));
}, },
printf: function (format: string, ...args: any[]): void { printf: function (_format: unknown, ...args: any[]): void {
const format = helper.string("printf", "format", _format);
updateDynamicRam("printf", getRamCost(Player, "printf")); updateDynamicRam("printf", getRamCost(Player, "printf"));
if (typeof format !== "string") { if (typeof format !== "string") {
throw makeRuntimeErrorMsg("printf", "First argument must be string for the format."); throw makeRuntimeErrorMsg("printf", "First argument must be string for the format.");
@ -771,7 +820,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
Terminal.print(`${workerScript.scriptRef.filename}: ${str}`); Terminal.print(`${workerScript.scriptRef.filename}: ${str}`);
}, },
tprintf: function (format: any, ...args: any): any { tprintf: function (_format: unknown, ...args: any[]): void {
const format = helper.string("printf", "format", _format);
updateDynamicRam("tprintf", getRamCost(Player, "tprintf")); updateDynamicRam("tprintf", getRamCost(Player, "tprintf"));
if (typeof format !== "string") { if (typeof format !== "string") {
throw makeRuntimeErrorMsg("tprintf", "First argument must be string for the format."); throw makeRuntimeErrorMsg("tprintf", "First argument must be string for the format.");
@ -796,14 +846,15 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
Terminal.print(`${str}`); Terminal.print(`${str}`);
}, },
clearLog: function (): any { clearLog: function (): void {
updateDynamicRam("clearLog", getRamCost(Player, "clearLog")); updateDynamicRam("clearLog", getRamCost(Player, "clearLog"));
workerScript.scriptRef.clearLog(); workerScript.scriptRef.clearLog();
}, },
disableLog: function (fn: any): any { disableLog: function (_fn: unknown): void {
const fn = helper.string("disableLog", "fn", _fn);
updateDynamicRam("disableLog", getRamCost(Player, "disableLog")); updateDynamicRam("disableLog", getRamCost(Player, "disableLog"));
if (fn === "ALL") { if (fn === "ALL") {
for (fn of Object.keys(possibleLogs)) { for (const fn of Object.keys(possibleLogs)) {
workerScript.disableLogs[fn] = true; workerScript.disableLogs[fn] = true;
} }
workerScript.log("disableLog", () => `Disabled logging for all functions`); workerScript.log("disableLog", () => `Disabled logging for all functions`);
@ -814,10 +865,11 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.log("disableLog", () => `Disabled logging for ${fn}`); workerScript.log("disableLog", () => `Disabled logging for ${fn}`);
} }
}, },
enableLog: function (fn: any): any { enableLog: function (_fn: unknown): void {
const fn = helper.string("enableLog", "fn", _fn);
updateDynamicRam("enableLog", getRamCost(Player, "enableLog")); updateDynamicRam("enableLog", getRamCost(Player, "enableLog"));
if (fn === "ALL") { if (fn === "ALL") {
for (fn of Object.keys(possibleLogs)) { for (const fn of Object.keys(possibleLogs)) {
delete workerScript.disableLogs[fn]; delete workerScript.disableLogs[fn];
} }
workerScript.log("enableLog", () => `Enabled logging for all functions`); workerScript.log("enableLog", () => `Enabled logging for all functions`);
@ -827,24 +879,25 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
delete workerScript.disableLogs[fn]; delete workerScript.disableLogs[fn];
workerScript.log("enableLog", () => `Enabled logging for ${fn}`); workerScript.log("enableLog", () => `Enabled logging for ${fn}`);
}, },
isLogEnabled: function (fn: any): any { isLogEnabled: function (_fn: unknown): boolean {
const fn = helper.string("isLogEnabled", "fn", _fn);
updateDynamicRam("isLogEnabled", getRamCost(Player, "isLogEnabled")); updateDynamicRam("isLogEnabled", getRamCost(Player, "isLogEnabled"));
if (possibleLogs[fn] === undefined) { if (possibleLogs[fn] === undefined) {
throw makeRuntimeErrorMsg("isLogEnabled", `Invalid argument: ${fn}.`); throw makeRuntimeErrorMsg("isLogEnabled", `Invalid argument: ${fn}.`);
} }
return !workerScript.disableLogs[fn]; return !workerScript.disableLogs[fn];
}, },
getScriptLogs: function (fn: any, hostname: any, ...scriptArgs: any): any { getScriptLogs: function (fn: any, hostname: any, ...scriptArgs: any[]): string[] {
updateDynamicRam("getScriptLogs", getRamCost(Player, "getScriptLogs")); updateDynamicRam("getScriptLogs", getRamCost(Player, "getScriptLogs"));
const runningScriptObj = getRunningScript(fn, hostname, "getScriptLogs", scriptArgs); const runningScriptObj = getRunningScript(fn, hostname, "getScriptLogs", scriptArgs);
if (runningScriptObj == null) { if (runningScriptObj == null) {
workerScript.log("getScriptLogs", () => getCannotFindRunningScriptErrorMessage(fn, hostname, scriptArgs)); workerScript.log("getScriptLogs", () => getCannotFindRunningScriptErrorMessage(fn, hostname, scriptArgs));
return ""; return [];
} }
return runningScriptObj.logs.slice(); return runningScriptObj.logs.slice();
}, },
tail: function (fn: any, hostname: any = workerScript.hostname, ...scriptArgs: any): any { tail: function (fn: any, hostname: any = workerScript.hostname, ...scriptArgs: any[]): void {
updateDynamicRam("tail", getRamCost(Player, "tail")); updateDynamicRam("tail", getRamCost(Player, "tail"));
let runningScriptObj; let runningScriptObj;
if (arguments.length === 0) { if (arguments.length === 0) {
@ -861,7 +914,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
LogBoxEvents.emit(runningScriptObj); LogBoxEvents.emit(runningScriptObj);
}, },
nuke: function (hostname: any): boolean { nuke: function (_hostname: unknown): boolean {
const hostname = helper.string("tail", "hostname", _hostname);
updateDynamicRam("nuke", getRamCost(Player, "nuke")); updateDynamicRam("nuke", getRamCost(Player, "nuke"));
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("nuke", "Takes 1 argument."); throw makeRuntimeErrorMsg("nuke", "Takes 1 argument.");
@ -885,7 +939,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.log("nuke", () => `Executed NUKE.exe virus on '${server.hostname}' to gain root access.`); workerScript.log("nuke", () => `Executed NUKE.exe virus on '${server.hostname}' to gain root access.`);
return true; return true;
}, },
brutessh: function (hostname: any): boolean { brutessh: function (_hostname: unknown): boolean {
const hostname = helper.string("brutessh", "hostname", _hostname);
updateDynamicRam("brutessh", getRamCost(Player, "brutessh")); updateDynamicRam("brutessh", getRamCost(Player, "brutessh"));
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("brutessh", "Takes 1 argument."); throw makeRuntimeErrorMsg("brutessh", "Takes 1 argument.");
@ -907,7 +962,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
return true; return true;
}, },
ftpcrack: function (hostname: any): boolean { ftpcrack: function (_hostname: unknown): boolean {
const hostname = helper.string("ftpcrack", "hostname", _hostname);
updateDynamicRam("ftpcrack", getRamCost(Player, "ftpcrack")); updateDynamicRam("ftpcrack", getRamCost(Player, "ftpcrack"));
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("ftpcrack", "Takes 1 argument."); throw makeRuntimeErrorMsg("ftpcrack", "Takes 1 argument.");
@ -929,7 +985,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
return true; return true;
}, },
relaysmtp: function (hostname: any): boolean { relaysmtp: function (_hostname: unknown): boolean {
const hostname = helper.string("relaysmtp", "hostname", _hostname);
updateDynamicRam("relaysmtp", getRamCost(Player, "relaysmtp")); updateDynamicRam("relaysmtp", getRamCost(Player, "relaysmtp"));
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("relaysmtp", "Takes 1 argument."); throw makeRuntimeErrorMsg("relaysmtp", "Takes 1 argument.");
@ -951,7 +1008,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
return true; return true;
}, },
httpworm: function (hostname: any): boolean { httpworm: function (_hostname: unknown): boolean {
const hostname = helper.string("httpworm", "hostname", _hostname);
updateDynamicRam("httpworm", getRamCost(Player, "httpworm")); updateDynamicRam("httpworm", getRamCost(Player, "httpworm"));
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("httpworm", "Takes 1 argument"); throw makeRuntimeErrorMsg("httpworm", "Takes 1 argument");
@ -973,7 +1031,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
return true; return true;
}, },
sqlinject: function (hostname: any): boolean { sqlinject: function (_hostname: unknown): boolean {
const hostname = helper.string("sqlinject", "hostname", _hostname);
updateDynamicRam("sqlinject", getRamCost(Player, "sqlinject")); updateDynamicRam("sqlinject", getRamCost(Player, "sqlinject"));
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("sqlinject", "Takes 1 argument."); throw makeRuntimeErrorMsg("sqlinject", "Takes 1 argument.");
@ -995,7 +1054,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
return true; return true;
}, },
run: function (scriptname: any, threads: any = 1, ...args: any[]): any { run: function (_scriptname: unknown, _threads: unknown = 1, ...args: any[]): number {
const scriptname = helper.string("run", "scriptname", _scriptname);
const threads = helper.number("run", "threads", _threads);
updateDynamicRam("run", getRamCost(Player, "run")); updateDynamicRam("run", getRamCost(Player, "run"));
if (scriptname === undefined) { if (scriptname === undefined) {
throw makeRuntimeErrorMsg("run", "Usage: run(scriptname, [numThreads], [arg1], [arg2]...)"); throw makeRuntimeErrorMsg("run", "Usage: run(scriptname, [numThreads], [arg1], [arg2]...)");
@ -1010,7 +1071,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return runScriptFromScript(Player, "run", scriptServer, scriptname, args, workerScript, threads); return runScriptFromScript(Player, "run", scriptServer, scriptname, args, workerScript, threads);
}, },
exec: function (scriptname: any, hostname: any, threads: any = 1, ...args: any[]): any { exec: function (_scriptname: unknown, _hostname: unknown, _threads: unknown = 1, ...args: any[]): number {
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")); updateDynamicRam("exec", getRamCost(Player, "exec"));
if (scriptname === undefined || hostname === undefined) { if (scriptname === undefined || hostname === undefined) {
throw makeRuntimeErrorMsg("exec", "Usage: exec(scriptname, server, [numThreads], [arg1], [arg2]...)"); throw makeRuntimeErrorMsg("exec", "Usage: exec(scriptname, server, [numThreads], [arg1], [arg2]...)");
@ -1021,7 +1085,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
const server = safeGetServer(hostname, "exec"); const server = safeGetServer(hostname, "exec");
return runScriptFromScript(Player, "exec", server, scriptname, args, workerScript, threads); return runScriptFromScript(Player, "exec", server, scriptname, args, workerScript, threads);
}, },
spawn: function (scriptname: any, threads: any = 1, ...args: any[]): any { spawn: function (_scriptname: unknown, _threads: unknown = 1, ...args: any[]): void {
const scriptname = helper.string("spawn", "scriptname", _scriptname);
const threads = helper.number("spawn", "threads", _threads);
updateDynamicRam("spawn", getRamCost(Player, "spawn")); updateDynamicRam("spawn", getRamCost(Player, "spawn"));
if (!scriptname || !threads) { if (!scriptname || !threads) {
throw makeRuntimeErrorMsg("spawn", "Usage: spawn(scriptname, threads)"); throw makeRuntimeErrorMsg("spawn", "Usage: spawn(scriptname, threads)");
@ -1047,7 +1113,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.log("spawn", () => "Exiting..."); workerScript.log("spawn", () => "Exiting...");
} }
}, },
kill: function (filename: any, hostname?: any, ...scriptArgs: any): any { kill: function (filename: any, hostname?: any, ...scriptArgs: any[]): boolean {
updateDynamicRam("kill", getRamCost(Player, "kill")); updateDynamicRam("kill", getRamCost(Player, "kill"));
let res; let res;
@ -1093,7 +1159,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return false; return false;
} }
}, },
killall: function (hostname: any = workerScript.hostname): any { killall: function (_hostname: unknown = workerScript.hostname): boolean {
const hostname = helper.string("killall", "hostname", _hostname);
updateDynamicRam("killall", getRamCost(Player, "killall")); updateDynamicRam("killall", getRamCost(Player, "killall"));
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("killall", "Takes 1 argument"); throw makeRuntimeErrorMsg("killall", "Takes 1 argument");
@ -1111,7 +1178,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return scriptsRunning; return scriptsRunning;
}, },
exit: function (): any { exit: function (): void {
updateDynamicRam("exit", getRamCost(Player, "exit")); updateDynamicRam("exit", getRamCost(Player, "exit"));
workerScript.running = false; // Prevent workerScript from "finishing execution naturally" workerScript.running = false; // Prevent workerScript from "finishing execution naturally"
if (killWorkerScript(workerScript)) { if (killWorkerScript(workerScript)) {
@ -1120,7 +1187,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.log("exit", () => "Failed. This is a bug. Report to dev."); workerScript.log("exit", () => "Failed. This is a bug. Report to dev.");
} }
}, },
scp: async function (scriptname: any, hostname1: any, hostname2?: any): Promise<boolean> { scp: async function (scriptname: any, _hostname1: unknown, hostname2?: any): Promise<boolean> {
const hostname1 = helper.string("scp", "hostname1", _hostname1);
updateDynamicRam("scp", getRamCost(Player, "scp")); updateDynamicRam("scp", getRamCost(Player, "scp"));
if (arguments.length !== 2 && arguments.length !== 3) { if (arguments.length !== 2 && arguments.length !== 3) {
throw makeRuntimeErrorMsg("scp", "Takes 2 or 3 arguments"); throw makeRuntimeErrorMsg("scp", "Takes 2 or 3 arguments");
@ -1277,7 +1345,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
newScript.updateRamUsage(Player, destServer.scripts).then(() => resolve(true)); newScript.updateRamUsage(Player, destServer.scripts).then(() => resolve(true));
}); });
}, },
ls: function (hostname: any, grep: any): any { ls: function (_hostname: unknown, _grep: unknown = ""): string[] {
const hostname = helper.string("ls", "hostname", _hostname);
const grep = helper.string("ls", "grep", _grep);
updateDynamicRam("ls", getRamCost(Player, "ls")); updateDynamicRam("ls", getRamCost(Player, "ls"));
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("ls", "Usage: ls(hostname/ip, [grep filter])"); throw makeRuntimeErrorMsg("ls", "Usage: ls(hostname/ip, [grep filter])");
@ -1344,7 +1414,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
allFiles.sort(); allFiles.sort();
return allFiles; return allFiles;
}, },
ps: function (hostname: any = workerScript.hostname): any { ps: function (_hostname: unknown = workerScript.hostname): ProcessInfo[] {
const hostname = helper.string("ps", "hostname", _hostname);
updateDynamicRam("ps", getRamCost(Player, "ps")); updateDynamicRam("ps", getRamCost(Player, "ps"));
const server = safeGetServer(hostname, "ps"); const server = safeGetServer(hostname, "ps");
const processes = []; const processes = [];
@ -1358,7 +1429,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
return processes; return processes;
}, },
hasRootAccess: function (hostname: any): any { hasRootAccess: function (_hostname: unknown): boolean {
const hostname = helper.string("hasRootAccess", "hostname", _hostname);
updateDynamicRam("hasRootAccess", getRamCost(Player, "hasRootAccess")); updateDynamicRam("hasRootAccess", getRamCost(Player, "hasRootAccess"));
if (hostname === undefined) { if (hostname === undefined) {
throw makeRuntimeErrorMsg("hasRootAccess", "Takes 1 argument"); throw makeRuntimeErrorMsg("hasRootAccess", "Takes 1 argument");
@ -1366,7 +1438,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
const server = safeGetServer(hostname, "hasRootAccess"); const server = safeGetServer(hostname, "hasRootAccess");
return server.hasAdminRights; return server.hasAdminRights;
}, },
getHostname: function (): any { getHostname: function (): string {
updateDynamicRam("getHostname", getRamCost(Player, "getHostname")); updateDynamicRam("getHostname", getRamCost(Player, "getHostname"));
const scriptServer = GetServer(workerScript.hostname); const scriptServer = GetServer(workerScript.hostname);
if (scriptServer == null) { if (scriptServer == null) {
@ -1374,13 +1446,13 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
return scriptServer.hostname; return scriptServer.hostname;
}, },
getHackingLevel: function (): any { getHackingLevel: function (): number {
updateDynamicRam("getHackingLevel", getRamCost(Player, "getHackingLevel")); updateDynamicRam("getHackingLevel", getRamCost(Player, "getHackingLevel"));
Player.updateSkillLevels(); Player.updateSkillLevels();
workerScript.log("getHackingLevel", () => `returned ${Player.hacking}`); workerScript.log("getHackingLevel", () => `returned ${Player.hacking}`);
return Player.hacking; return Player.hacking;
}, },
getHackingMultipliers: function (): any { getHackingMultipliers: function (): HackingMultipliers {
updateDynamicRam("getHackingMultipliers", getRamCost(Player, "getHackingMultipliers")); updateDynamicRam("getHackingMultipliers", getRamCost(Player, "getHackingMultipliers"));
return { return {
chance: Player.hacking_chance_mult, chance: Player.hacking_chance_mult,
@ -1389,7 +1461,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
growth: Player.hacking_grow_mult, growth: Player.hacking_grow_mult,
}; };
}, },
getHacknetMultipliers: function (): any { getHacknetMultipliers: function (): HacknetMultipliers {
updateDynamicRam("getHacknetMultipliers", getRamCost(Player, "getHacknetMultipliers")); updateDynamicRam("getHacknetMultipliers", getRamCost(Player, "getHacknetMultipliers"));
return { return {
production: Player.hacknet_node_money_mult, production: Player.hacknet_node_money_mult,
@ -1399,7 +1471,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
levelCost: Player.hacknet_node_level_cost_mult, levelCost: Player.hacknet_node_level_cost_mult,
}; };
}, },
getBitNodeMultipliers: function (): any { getBitNodeMultipliers: function (): IBNMults {
updateDynamicRam("getBitNodeMultipliers", getRamCost(Player, "getBitNodeMultipliers")); updateDynamicRam("getBitNodeMultipliers", getRamCost(Player, "getBitNodeMultipliers"));
if (SourceFileFlags[5] <= 0 && Player.bitNodeN !== 5) { if (SourceFileFlags[5] <= 0 && Player.bitNodeN !== 5) {
throw makeRuntimeErrorMsg("getBitNodeMultipliers", "Requires Source-File 5 to run."); throw makeRuntimeErrorMsg("getBitNodeMultipliers", "Requires Source-File 5 to run.");
@ -1407,7 +1479,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
const copy = Object.assign({}, BitNodeMultipliers); const copy = Object.assign({}, BitNodeMultipliers);
return copy; return copy;
}, },
getServer: function (hostname: any = workerScript.hostname): any { getServer: function (_hostname: unknown = workerScript.hostname): IServerDef {
const hostname = helper.string("getServer", "hostname", _hostname);
updateDynamicRam("getServer", getRamCost(Player, "getServer")); updateDynamicRam("getServer", getRamCost(Player, "getServer"));
const server = safeGetServer(hostname, "getServer"); const server = safeGetServer(hostname, "getServer");
const copy = Object.assign({}, server) as any; const copy = Object.assign({}, server) as any;
@ -1430,7 +1503,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
if (!copy.serverGrowth) copy.serverGrowth = 0; if (!copy.serverGrowth) copy.serverGrowth = 0;
return copy; return copy;
}, },
getServerMoneyAvailable: function (hostname: any): any { getServerMoneyAvailable: function (_hostname: unknown): number {
const hostname = helper.string("getServerMoneyAvailable", "hostname", _hostname);
updateDynamicRam("getServerMoneyAvailable", getRamCost(Player, "getServerMoneyAvailable")); updateDynamicRam("getServerMoneyAvailable", getRamCost(Player, "getServerMoneyAvailable"));
const server = safeGetServer(hostname, "getServerMoneyAvailable"); const server = safeGetServer(hostname, "getServerMoneyAvailable");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
@ -1454,7 +1528,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
); );
return server.moneyAvailable; return server.moneyAvailable;
}, },
getServerSecurityLevel: function (hostname: any): any { getServerSecurityLevel: function (_hostname: unknown): number {
const hostname = helper.string("getServerSecurityLevel", "hostname", _hostname);
updateDynamicRam("getServerSecurityLevel", getRamCost(Player, "getServerSecurityLevel")); updateDynamicRam("getServerSecurityLevel", getRamCost(Player, "getServerSecurityLevel"));
const server = safeGetServer(hostname, "getServerSecurityLevel"); const server = safeGetServer(hostname, "getServerSecurityLevel");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
@ -1470,7 +1545,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
); );
return server.hackDifficulty; return server.hackDifficulty;
}, },
getServerBaseSecurityLevel: function (hostname: any): any { getServerBaseSecurityLevel: function (_hostname: unknown): number {
const hostname = helper.string("getServerBaseSecurityLevel", "hostname", _hostname);
updateDynamicRam("getServerBaseSecurityLevel", getRamCost(Player, "getServerBaseSecurityLevel")); updateDynamicRam("getServerBaseSecurityLevel", getRamCost(Player, "getServerBaseSecurityLevel"));
workerScript.log( workerScript.log(
"getServerBaseSecurityLevel", "getServerBaseSecurityLevel",
@ -1490,7 +1566,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
); );
return server.baseDifficulty; return server.baseDifficulty;
}, },
getServerMinSecurityLevel: function (hostname: any): any { getServerMinSecurityLevel: function (_hostname: unknown): number {
const hostname = helper.string("getServerMinSecurityLevel", "hostname", _hostname);
updateDynamicRam("getServerMinSecurityLevel", getRamCost(Player, "getServerMinSecurityLevel")); updateDynamicRam("getServerMinSecurityLevel", getRamCost(Player, "getServerMinSecurityLevel"));
const server = safeGetServer(hostname, "getServerMinSecurityLevel"); const server = safeGetServer(hostname, "getServerMinSecurityLevel");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
@ -1506,7 +1583,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
); );
return server.minDifficulty; return server.minDifficulty;
}, },
getServerRequiredHackingLevel: function (hostname: any): any { getServerRequiredHackingLevel: function (_hostname: unknown): number {
const hostname = helper.string("getServerRequiredHackingLevel", "hostname", _hostname);
updateDynamicRam("getServerRequiredHackingLevel", getRamCost(Player, "getServerRequiredHackingLevel")); updateDynamicRam("getServerRequiredHackingLevel", getRamCost(Player, "getServerRequiredHackingLevel"));
const server = safeGetServer(hostname, "getServerRequiredHackingLevel"); const server = safeGetServer(hostname, "getServerRequiredHackingLevel");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
@ -1522,7 +1600,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
); );
return server.requiredHackingSkill; return server.requiredHackingSkill;
}, },
getServerMaxMoney: function (hostname: any): any { getServerMaxMoney: function (_hostname: unknown): number {
const hostname = helper.string("getServerMaxMoney", "hostname", _hostname);
updateDynamicRam("getServerMaxMoney", getRamCost(Player, "getServerMaxMoney")); updateDynamicRam("getServerMaxMoney", getRamCost(Player, "getServerMaxMoney"));
const server = safeGetServer(hostname, "getServerMaxMoney"); const server = safeGetServer(hostname, "getServerMaxMoney");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
@ -1538,7 +1617,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
); );
return server.moneyMax; return server.moneyMax;
}, },
getServerGrowth: function (hostname: any): any { getServerGrowth: function (_hostname: unknown): number {
const hostname = helper.string("getServerGrowth", "hostname", _hostname);
updateDynamicRam("getServerGrowth", getRamCost(Player, "getServerGrowth")); updateDynamicRam("getServerGrowth", getRamCost(Player, "getServerGrowth"));
const server = safeGetServer(hostname, "getServerGrowth"); const server = safeGetServer(hostname, "getServerGrowth");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
@ -1551,7 +1631,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.log("getServerGrowth", () => `returned ${server.serverGrowth} for '${server.hostname}'`); workerScript.log("getServerGrowth", () => `returned ${server.serverGrowth} for '${server.hostname}'`);
return server.serverGrowth; return server.serverGrowth;
}, },
getServerNumPortsRequired: function (hostname: any): any { getServerNumPortsRequired: function (_hostname: unknown): number {
const hostname = helper.string("getServerNumPortsRequired", "hostname", _hostname);
updateDynamicRam("getServerNumPortsRequired", getRamCost(Player, "getServerNumPortsRequired")); updateDynamicRam("getServerNumPortsRequired", getRamCost(Player, "getServerNumPortsRequired"));
const server = safeGetServer(hostname, "getServerNumPortsRequired"); const server = safeGetServer(hostname, "getServerNumPortsRequired");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
@ -1567,7 +1648,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
); );
return server.numOpenPortsRequired; return server.numOpenPortsRequired;
}, },
getServerRam: function (hostname: any): any { getServerRam: function (_hostname: unknown): [number, number] {
const hostname = helper.string("getServerRam", "hostname", _hostname);
updateDynamicRam("getServerRam", getRamCost(Player, "getServerRam")); updateDynamicRam("getServerRam", getRamCost(Player, "getServerRam"));
workerScript.log( workerScript.log(
"getServerRam", "getServerRam",
@ -1580,23 +1662,28 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
); );
return [server.maxRam, server.ramUsed]; return [server.maxRam, server.ramUsed];
}, },
getServerMaxRam: function (hostname: any): any { getServerMaxRam: function (_hostname: unknown): number {
const hostname = helper.string("getServerMaxRam", "hostname", _hostname);
updateDynamicRam("getServerMaxRam", getRamCost(Player, "getServerMaxRam")); updateDynamicRam("getServerMaxRam", getRamCost(Player, "getServerMaxRam"));
const server = safeGetServer(hostname, "getServerMaxRam"); const server = safeGetServer(hostname, "getServerMaxRam");
workerScript.log("getServerMaxRam", () => `returned ${numeralWrapper.formatRAM(server.maxRam)}`); workerScript.log("getServerMaxRam", () => `returned ${numeralWrapper.formatRAM(server.maxRam)}`);
return server.maxRam; return server.maxRam;
}, },
getServerUsedRam: function (hostname: any): any { getServerUsedRam: function (_hostname: unknown): number {
const hostname = helper.string("getServerUsedRam", "hostname", _hostname);
updateDynamicRam("getServerUsedRam", getRamCost(Player, "getServerUsedRam")); updateDynamicRam("getServerUsedRam", getRamCost(Player, "getServerUsedRam"));
const server = safeGetServer(hostname, "getServerUsedRam"); const server = safeGetServer(hostname, "getServerUsedRam");
workerScript.log("getServerUsedRam", () => `returned ${numeralWrapper.formatRAM(server.ramUsed)}`); workerScript.log("getServerUsedRam", () => `returned ${numeralWrapper.formatRAM(server.ramUsed)}`);
return server.ramUsed; return server.ramUsed;
}, },
serverExists: function (hostname: any): any { serverExists: function (_hostname: unknown): boolean {
const hostname = helper.string("serverExists", "hostname", _hostname);
updateDynamicRam("serverExists", getRamCost(Player, "serverExists")); updateDynamicRam("serverExists", getRamCost(Player, "serverExists"));
return GetServer(hostname) !== null; return GetServer(hostname) !== null;
}, },
fileExists: function (filename: any, hostname: any = workerScript.hostname): any { fileExists: function (_filename: unknown, _hostname: unknown = workerScript.hostname): boolean {
const filename = helper.string("fileExists", "filename", _filename);
const hostname = helper.string("fileExists", "hostname", _hostname);
updateDynamicRam("fileExists", getRamCost(Player, "fileExists")); updateDynamicRam("fileExists", getRamCost(Player, "fileExists"));
if (filename === undefined) { if (filename === undefined) {
throw makeRuntimeErrorMsg("fileExists", "Usage: fileExists(scriptname, [server])"); throw makeRuntimeErrorMsg("fileExists", "Usage: fileExists(scriptname, [server])");
@ -1620,7 +1707,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
const txtFile = getTextFile(filename, server); const txtFile = getTextFile(filename, server);
return txtFile != null; return txtFile != null;
}, },
isRunning: function (fn: any, hostname: any = workerScript.hostname, ...scriptArgs: any): any { isRunning: function (fn: any, hostname: any = workerScript.hostname, ...scriptArgs: any[]): boolean {
updateDynamicRam("isRunning", getRamCost(Player, "isRunning")); updateDynamicRam("isRunning", getRamCost(Player, "isRunning"));
if (fn === undefined || hostname === undefined) { if (fn === undefined || hostname === undefined) {
throw makeRuntimeErrorMsg("isRunning", "Usage: isRunning(scriptname, server, [arg1], [arg2]...)"); throw makeRuntimeErrorMsg("isRunning", "Usage: isRunning(scriptname, server, [arg1], [arg2]...)");
@ -1631,17 +1718,18 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return getRunningScript(fn, hostname, "isRunning", scriptArgs) != null; return getRunningScript(fn, hostname, "isRunning", scriptArgs) != null;
} }
}, },
getPurchasedServerLimit: function (): any { getPurchasedServerLimit: function (): number {
updateDynamicRam("getPurchasedServerLimit", getRamCost(Player, "getPurchasedServerLimit")); updateDynamicRam("getPurchasedServerLimit", getRamCost(Player, "getPurchasedServerLimit"));
return getPurchaseServerLimit(); return getPurchaseServerLimit();
}, },
getPurchasedServerMaxRam: function (): any { getPurchasedServerMaxRam: function (): number {
updateDynamicRam("getPurchasedServerMaxRam", getRamCost(Player, "getPurchasedServerMaxRam")); updateDynamicRam("getPurchasedServerMaxRam", getRamCost(Player, "getPurchasedServerMaxRam"));
return getPurchaseServerMaxRam(); return getPurchaseServerMaxRam();
}, },
getPurchasedServerCost: function (ram: any): any { getPurchasedServerCost: function (_ram: unknown): number {
const ram = helper.number("getPurchasedServerCost", "ram", _ram);
updateDynamicRam("getPurchasedServerCost", getRamCost(Player, "getPurchasedServerCost")); updateDynamicRam("getPurchasedServerCost", getRamCost(Player, "getPurchasedServerCost"));
const cost = getPurchaseServerCost(ram); const cost = getPurchaseServerCost(ram);
@ -1652,10 +1740,10 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return cost; return cost;
}, },
purchaseServer: function (aname: any, aram: any): any { purchaseServer: function (_name: unknown, _ram: unknown): string {
const name = helper.string("purchaseServer", "name", _name);
const ram = helper.number("purchaseServer", "ram", _ram);
if (arguments.length !== 2) throw makeRuntimeErrorMsg("purchaseServer", "Takes 2 arguments"); if (arguments.length !== 2) throw makeRuntimeErrorMsg("purchaseServer", "Takes 2 arguments");
const name = helper.string("purchaseServer", "name", aname);
const ram = helper.number("purchaseServer", "ram", aram);
updateDynamicRam("purchaseServer", getRamCost(Player, "purchaseServer")); updateDynamicRam("purchaseServer", getRamCost(Player, "purchaseServer"));
let hostnameStr = String(name); let hostnameStr = String(name);
hostnameStr = hostnameStr.replace(/\s+/g, ""); hostnameStr = hostnameStr.replace(/\s+/g, "");
@ -1716,7 +1804,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
); );
return newServ.hostname; return newServ.hostname;
}, },
deleteServer: function (name: any): any { deleteServer: function (_name: unknown): boolean {
const name = helper.string("purchaseServer", "name", _name);
updateDynamicRam("deleteServer", getRamCost(Player, "deleteServer")); updateDynamicRam("deleteServer", getRamCost(Player, "deleteServer"));
let hostnameStr = String(name); let hostnameStr = String(name);
hostnameStr = hostnameStr.replace(/\s\s+/g, ""); hostnameStr = hostnameStr.replace(/\s\s+/g, "");
@ -1792,7 +1881,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
); );
return false; return false;
}, },
getPurchasedServers: function (): any { getPurchasedServers: function (): string[] {
updateDynamicRam("getPurchasedServers", getRamCost(Player, "getPurchasedServers")); updateDynamicRam("getPurchasedServers", getRamCost(Player, "getPurchasedServers"));
const res: string[] = []; const res: string[] = [];
Player.purchasedServers.forEach(function (hostname) { Player.purchasedServers.forEach(function (hostname) {
@ -1800,7 +1889,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}); });
return res; return res;
}, },
writePort: function (port: any, data: any = ""): any { writePort: function (_port: unknown, data: any = ""): Promise<any> {
const port = helper.number("writePort", "port", _port);
updateDynamicRam("writePort", getRamCost(Player, "writePort")); updateDynamicRam("writePort", getRamCost(Player, "writePort"));
if (typeof data !== "string" && typeof data !== "number") { if (typeof data !== "string" && typeof data !== "number") {
throw makeRuntimeErrorMsg( throw makeRuntimeErrorMsg(
@ -1811,7 +1901,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
const iport = helper.getValidPort("writePort", port); const iport = helper.getValidPort("writePort", port);
return Promise.resolve(iport.write(data)); return Promise.resolve(iport.write(data));
}, },
write: function (port: any, data: any = "", mode: any = "a"): any { write: function (_port: unknown, data: any = "", _mode: unknown = "a"): Promise<void> {
const port = helper.string("write", "port", _port);
const mode = helper.string("write", "mode", _mode);
updateDynamicRam("write", getRamCost(Player, "write")); updateDynamicRam("write", getRamCost(Player, "write"));
if (isString(port)) { if (isString(port)) {
// Write to script or text file // Write to script or text file
@ -1864,7 +1956,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
throw makeRuntimeErrorMsg("write", `Invalid argument: ${port}`); throw makeRuntimeErrorMsg("write", `Invalid argument: ${port}`);
} }
}, },
tryWritePort: function (port: any, data: any = ""): any { tryWritePort: function (_port: unknown, data: any = ""): Promise<any> {
let port = helper.number("tryWritePort", "port", _port);
updateDynamicRam("tryWritePort", getRamCost(Player, "tryWritePort")); updateDynamicRam("tryWritePort", getRamCost(Player, "tryWritePort"));
if (typeof data !== "string" && typeof data !== "number") { if (typeof data !== "string" && typeof data !== "number") {
throw makeRuntimeErrorMsg( throw makeRuntimeErrorMsg(
@ -1889,14 +1982,16 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
throw makeRuntimeErrorMsg("tryWritePort", `Invalid argument: ${port}`); throw makeRuntimeErrorMsg("tryWritePort", `Invalid argument: ${port}`);
} }
}, },
readPort: function (port: any): any { readPort: function (_port: unknown): any {
const port = helper.number("readPort", "port", _port);
updateDynamicRam("readPort", getRamCost(Player, "readPort")); updateDynamicRam("readPort", getRamCost(Player, "readPort"));
// Read from port // Read from port
const iport = helper.getValidPort("readPort", port); const iport = helper.getValidPort("readPort", port);
const x = iport.read(); const x = iport.read();
return x; return x;
}, },
read: function (port: any): any { read: function (_port: unknown): string {
const port = helper.string("read", "port", _port);
updateDynamicRam("read", getRamCost(Player, "read")); updateDynamicRam("read", getRamCost(Player, "read"));
if (isString(port)) { if (isString(port)) {
// Read from script or text file // Read from script or text file
@ -1925,13 +2020,15 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
throw makeRuntimeErrorMsg("read", `Invalid argument: ${port}`); throw makeRuntimeErrorMsg("read", `Invalid argument: ${port}`);
} }
}, },
peek: function (port: any): any { peek: function (_port: unknown): any {
const port = helper.number("peek", "port", _port);
updateDynamicRam("peek", getRamCost(Player, "peek")); updateDynamicRam("peek", getRamCost(Player, "peek"));
const iport = helper.getValidPort("peek", port); const iport = helper.getValidPort("peek", port);
const x = iport.peek(); const x = iport.peek();
return x; return x;
}, },
clear: function (file: any): any { clear: function (_file: unknown): void {
const file = helper.string("peek", "file", _file);
updateDynamicRam("clear", getRamCost(Player, "clear")); updateDynamicRam("clear", getRamCost(Player, "clear"));
if (isString(file)) { if (isString(file)) {
// Clear text file // Clear text file
@ -1947,20 +2044,22 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} else { } else {
throw makeRuntimeErrorMsg("clear", `Invalid argument: ${file}`); throw makeRuntimeErrorMsg("clear", `Invalid argument: ${file}`);
} }
return 0;
}, },
clearPort: function (port: any): any { clearPort: function (_port: unknown): void {
const port = helper.number("clearPort", "port", _port);
updateDynamicRam("clearPort", getRamCost(Player, "clearPort")); updateDynamicRam("clearPort", getRamCost(Player, "clearPort"));
// Clear port // Clear port
const iport = helper.getValidPort("clearPort", port); const iport = helper.getValidPort("clearPort", port);
return iport.clear(); iport.clear();
}, },
getPortHandle: function (port: any): IPort { getPortHandle: function (_port: unknown): IPort {
const port = helper.number("getPortHandle", "port", _port);
updateDynamicRam("getPortHandle", getRamCost(Player, "getPortHandle")); updateDynamicRam("getPortHandle", getRamCost(Player, "getPortHandle"));
const iport = helper.getValidPort("getPortHandle", port); const iport = helper.getValidPort("getPortHandle", port);
return iport; return iport;
}, },
rm: function (fn: any, hostname: any): any { rm: function (_fn: unknown, hostname: any): boolean {
const fn = helper.string("rm", "fn", _fn);
updateDynamicRam("rm", getRamCost(Player, "rm")); updateDynamicRam("rm", getRamCost(Player, "rm"));
if (hostname == null || hostname === "") { if (hostname == null || hostname === "") {
@ -1975,7 +2074,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return status.res; return status.res;
}, },
scriptRunning: function (scriptname: any, hostname: any): any { scriptRunning: function (_scriptname: unknown, _hostname: unknown): boolean {
const scriptname = helper.string("scriptRunning", "scriptname", _scriptname);
const hostname = helper.string("scriptRunning", "hostname", _hostname);
updateDynamicRam("scriptRunning", getRamCost(Player, "scriptRunning")); updateDynamicRam("scriptRunning", getRamCost(Player, "scriptRunning"));
const server = safeGetServer(hostname, "scriptRunning"); const server = safeGetServer(hostname, "scriptRunning");
for (let i = 0; i < server.runningScripts.length; ++i) { for (let i = 0; i < server.runningScripts.length; ++i) {
@ -1985,7 +2086,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
return false; return false;
}, },
scriptKill: function (scriptname: any, hostname: any): any { scriptKill: function (_scriptname: unknown, _hostname: unknown): boolean {
const scriptname = helper.string("scriptKill", "scriptname", _scriptname);
const hostname = helper.string("scriptKill", "hostname", _hostname);
updateDynamicRam("scriptKill", getRamCost(Player, "scriptKill")); updateDynamicRam("scriptKill", getRamCost(Player, "scriptKill"));
const server = safeGetServer(hostname, "scriptKill"); const server = safeGetServer(hostname, "scriptKill");
let suc = false; let suc = false;
@ -1998,11 +2101,13 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
return suc; return suc;
}, },
getScriptName: function (): any { getScriptName: function (): string {
updateDynamicRam("getScriptName", getRamCost(Player, "getScriptName")); updateDynamicRam("getScriptName", getRamCost(Player, "getScriptName"));
return workerScript.name; return workerScript.name;
}, },
getScriptRam: function (scriptname: any, hostname: any = workerScript.hostname): any { getScriptRam: function (_scriptname: unknown, _hostname: unknown = workerScript.hostname): number {
const scriptname = helper.string("getScriptRam", "scriptname", _scriptname);
const hostname = helper.string("getScriptRam", "hostname", _hostname);
updateDynamicRam("getScriptRam", getRamCost(Player, "getScriptRam")); updateDynamicRam("getScriptRam", getRamCost(Player, "getScriptRam"));
const server = safeGetServer(hostname, "getScriptRam"); const server = safeGetServer(hostname, "getScriptRam");
for (let i = 0; i < server.scripts.length; ++i) { for (let i = 0; i < server.scripts.length; ++i) {
@ -2012,7 +2117,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
} }
return 0; return 0;
}, },
getRunningScript: function (fn: any, hostname: any, ...args: any[]): any { getRunningScript: function (fn: any, hostname: any, ...args: any[]): IRunningScriptDef | null {
updateDynamicRam("getRunningScript", getRamCost(Player, "getRunningScript")); updateDynamicRam("getRunningScript", getRamCost(Player, "getRunningScript"));
let runningScript; let runningScript;
@ -2040,7 +2145,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
threads: runningScript.threads, threads: runningScript.threads,
}; };
}, },
getHackTime: function (hostname: any): any { getHackTime: function (_hostname: unknown = workerScript.hostname): number {
const hostname = helper.string("getHackTime", "hostname", _hostname);
updateDynamicRam("getHackTime", getRamCost(Player, "getHackTime")); updateDynamicRam("getHackTime", getRamCost(Player, "getHackTime"));
const server = safeGetServer(hostname, "getHackTime"); const server = safeGetServer(hostname, "getHackTime");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
@ -2053,7 +2159,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return calculateHackingTime(server, Player) * 1000; return calculateHackingTime(server, Player) * 1000;
}, },
getGrowTime: function (hostname: any): any { getGrowTime: function (_hostname: unknown = workerScript.hostname): number {
const hostname = helper.string("getGrowTime", "hostname", _hostname);
updateDynamicRam("getGrowTime", getRamCost(Player, "getGrowTime")); updateDynamicRam("getGrowTime", getRamCost(Player, "getGrowTime"));
const server = safeGetServer(hostname, "getGrowTime"); const server = safeGetServer(hostname, "getGrowTime");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
@ -2066,7 +2173,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return calculateGrowTime(server, Player) * 1000; return calculateGrowTime(server, Player) * 1000;
}, },
getWeakenTime: function (hostname: any = workerScript.hostname): any { getWeakenTime: function (_hostname: unknown = workerScript.hostname): number {
const hostname = helper.string("getWeakenTime", "hostname", _hostname);
updateDynamicRam("getWeakenTime", getRamCost(Player, "getWeakenTime")); updateDynamicRam("getWeakenTime", getRamCost(Player, "getWeakenTime"));
const server = safeGetServer(hostname, "getWeakenTime"); const server = safeGetServer(hostname, "getWeakenTime");
if (!(server instanceof Server)) { if (!(server instanceof Server)) {
@ -2108,7 +2216,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return runningScriptObj.onlineMoneyMade / runningScriptObj.onlineRunningTime; return runningScriptObj.onlineMoneyMade / runningScriptObj.onlineRunningTime;
} }
}, },
getScriptExpGain: function (scriptname?: any, hostname?: any, ...args: any[]): any { getScriptExpGain: function (scriptname?: any, hostname?: any, ...args: any[]): number {
updateDynamicRam("getScriptExpGain", getRamCost(Player, "getScriptExpGain")); updateDynamicRam("getScriptExpGain", getRamCost(Player, "getScriptExpGain"));
if (arguments.length === 0) { if (arguments.length === 0) {
let total = 0; let total = 0;
@ -2130,40 +2238,42 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime; return runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime;
} }
}, },
nFormat: function (n: any, format: any): any { nFormat: function (_n: unknown, _format: unknown): string {
const n = helper.number("nFormat", "n", _n);
const format = helper.string("nFormat", "format", _format);
updateDynamicRam("nFormat", getRamCost(Player, "nFormat")); updateDynamicRam("nFormat", getRamCost(Player, "nFormat"));
if (isNaN(n) || isNaN(parseFloat(n)) || typeof format !== "string") { if (isNaN(n)) {
return ""; return "";
} }
return numeralWrapper.format(parseFloat(n), format); return numeralWrapper.format(n, format);
}, },
tFormat: function (milliseconds: any, milliPrecision: any = false): any { tFormat: function (_milliseconds: unknown, _milliPrecision: unknown = false): string {
const milliseconds = helper.number("tFormat", "milliseconds", _milliseconds);
const milliPrecision = helper.boolean(_milliPrecision);
updateDynamicRam("tFormat", getRamCost(Player, "tFormat")); updateDynamicRam("tFormat", getRamCost(Player, "tFormat"));
return convertTimeMsToTimeElapsedString(milliseconds, milliPrecision); return convertTimeMsToTimeElapsedString(milliseconds, milliPrecision);
}, },
getTimeSinceLastAug: function (): any { getTimeSinceLastAug: function (): number {
updateDynamicRam("getTimeSinceLastAug", getRamCost(Player, "getTimeSinceLastAug")); updateDynamicRam("getTimeSinceLastAug", getRamCost(Player, "getTimeSinceLastAug"));
return Player.playtimeSinceLastAug; return Player.playtimeSinceLastAug;
}, },
alert: function (message: any): void { alert: function (_message: unknown): void {
const message = helper.string("alert", "message", _message);
updateDynamicRam("alert", getRamCost(Player, "alert")); updateDynamicRam("alert", getRamCost(Player, "alert"));
message = argsToString([message]);
dialogBoxCreate(message); dialogBoxCreate(message);
}, },
toast: function (message: any, variant: any = "success", duration: any = 2000): void { toast: function (_message: unknown, _variant: unknown = "success", duration: any = 2000): void {
const message = helper.string("toast", "message", _message);
const variant = helper.string("toast", "variant", _variant);
updateDynamicRam("toast", getRamCost(Player, "toast")); updateDynamicRam("toast", getRamCost(Player, "toast"));
if (!["success", "info", "warning", "error"].includes(variant)) if (!["success", "info", "warning", "error"].includes(variant))
throw new Error(`variant must be one of "success", "info", "warning", or "error"`); throw new Error(`variant must be one of "success", "info", "warning", or "error"`);
SnackbarEvents.emit(message, variant as any, duration);
message = argsToString([message]);
SnackbarEvents.emit(message, variant, duration);
}, },
prompt: function (txt: any, options?: { type?: string; options?: string[] }): any { prompt: function (_txt: unknown, options?: { type?: string; options?: string[] }): Promise<boolean | string> {
const txt = helper.string("toast", "txt", _txt);
updateDynamicRam("prompt", getRamCost(Player, "prompt")); updateDynamicRam("prompt", getRamCost(Player, "prompt"));
if (!isString(txt)) {
txt = JSON.stringify(txt);
}
return new Promise(function (resolve) { return new Promise(function (resolve) {
PromptEvent.emit({ PromptEvent.emit({
@ -2173,7 +2283,14 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}); });
}); });
}, },
wget: async function (url: any, target: any, hostname: any = workerScript.hostname): Promise<boolean> { wget: async function (
_url: unknown,
_target: unknown,
_hostname: unknown = workerScript.hostname,
): Promise<boolean> {
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")); updateDynamicRam("wget", getRamCost(Player, "wget"));
if (!isScriptFilename(target) && !target.endsWith(".txt")) { if (!isScriptFilename(target) && !target.endsWith(".txt")) {
workerScript.log("wget", () => `Invalid target file: '${target}'. Must be a script or text file.`); workerScript.log("wget", () => `Invalid target file: '${target}'. Must be a script or text file.`);
@ -2211,7 +2328,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}); });
}); });
}, },
getFavorToDonate: function (): any { getFavorToDonate: function (): number {
updateDynamicRam("getFavorToDonate", getRamCost(Player, "getFavorToDonate")); updateDynamicRam("getFavorToDonate", getRamCost(Player, "getFavorToDonate"));
return Math.floor(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction); return Math.floor(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction);
}, },
@ -2332,11 +2449,12 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
f(); f();
}; // Wrap the user function to prevent WorkerScript leaking as 'this' }; // Wrap the user function to prevent WorkerScript leaking as 'this'
}, },
mv: function (host: string, source: string, destination: string): void { mv: function (_host: unknown, _source: unknown, _destination: unknown): void {
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")); updateDynamicRam("mv", getRamCost(Player, "mv"));
if (arguments.length != 3) throw makeRuntimeErrorMsg("mv", "Takes 3 argument.");
if (!isValidFilePath(source)) throw makeRuntimeErrorMsg("mv", `Invalid filename: '${source}'`); if (!isValidFilePath(source)) throw makeRuntimeErrorMsg("mv", `Invalid filename: '${source}'`);
if (!isValidFilePath(destination)) throw makeRuntimeErrorMsg("mv", `Invalid filename: '${destination}'`); if (!isValidFilePath(destination)) throw makeRuntimeErrorMsg("mv", `Invalid filename: '${destination}'`);

@ -5,13 +5,14 @@ import { Bladeburner } from "../Bladeburner/Bladeburner";
import { getRamCost } from "../Netscript/RamCostGenerator"; import { getRamCost } from "../Netscript/RamCostGenerator";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { Bladeburner as INetscriptBladeburner, BladeburnerCurAction } from "../ScriptEditor/NetscriptDefinitions"; import { Bladeburner as INetscriptBladeburner, BladeburnerCurAction } from "../ScriptEditor/NetscriptDefinitions";
import { IAction } from "src/Bladeburner/IAction";
export function NetscriptBladeburner( export function NetscriptBladeburner(
player: IPlayer, player: IPlayer,
workerScript: WorkerScript, workerScript: WorkerScript,
helper: INetscriptHelper, helper: INetscriptHelper,
): INetscriptBladeburner { ): INetscriptBladeburner {
const checkBladeburnerAccess = function (func: any, skipjoined: any = false): void { const checkBladeburnerAccess = function (func: string, skipjoined = false): void {
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Must have joined bladeburner"); if (bladeburner === null) throw new Error("Must have joined bladeburner");
const apiAccess = const apiAccess =
@ -32,7 +33,7 @@ export function NetscriptBladeburner(
} }
}; };
const checkBladeburnerCity = function (func: any, city: any): void { const checkBladeburnerCity = function (func: string, city: string): void {
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Must have joined bladeburner"); if (bladeburner === null) throw new Error("Must have joined bladeburner");
if (!bladeburner.cities.hasOwnProperty(city)) { if (!bladeburner.cities.hasOwnProperty(city)) {
@ -40,7 +41,7 @@ export function NetscriptBladeburner(
} }
}; };
const getBladeburnerActionObject = function (func: any, type: any, name: any): any { const getBladeburnerActionObject = function (func: string, type: string, name: string): IAction {
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Must have joined bladeburner"); if (bladeburner === null) throw new Error("Must have joined bladeburner");
const actionId = bladeburner.getActionIdFromTypeAndName(type, name); const actionId = bladeburner.getActionIdFromTypeAndName(type, name);
@ -77,10 +78,11 @@ export function NetscriptBladeburner(
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getBlackOpNamesNetscriptFn(); return bladeburner.getBlackOpNamesNetscriptFn();
}, },
getBlackOpRank: function (name: any = ""): number { getBlackOpRank: function (_blackOpName: unknown): number {
const blackOpName = helper.string("getBlackOpRank", "blackOpName", _blackOpName);
helper.updateDynamicRam("getBlackOpRank", getRamCost(player, "bladeburner", "getBlackOpRank")); helper.updateDynamicRam("getBlackOpRank", getRamCost(player, "bladeburner", "getBlackOpRank"));
checkBladeburnerAccess("getBlackOpRank"); checkBladeburnerAccess("getBlackOpRank");
const action: any = getBladeburnerActionObject("getBlackOpRank", "blackops", name); const action: any = getBladeburnerActionObject("getBlackOpRank", "blackops", blackOpName);
return action.reqdRank; return action.reqdRank;
}, },
getGeneralActionNames: function (): string[] { getGeneralActionNames: function (): string[] {
@ -97,7 +99,9 @@ export function NetscriptBladeburner(
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getSkillNamesNetscriptFn(); return bladeburner.getSkillNamesNetscriptFn();
}, },
startAction: function (type: any = "", name: any = ""): boolean { startAction: function (_type: unknown, _name: unknown): boolean {
const type = helper.string("startAction", "type", _type);
const name = helper.string("startAction", "name", _name);
helper.updateDynamicRam("startAction", getRamCost(player, "bladeburner", "startAction")); helper.updateDynamicRam("startAction", getRamCost(player, "bladeburner", "startAction"));
checkBladeburnerAccess("startAction"); checkBladeburnerAccess("startAction");
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
@ -122,7 +126,9 @@ export function NetscriptBladeburner(
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getTypeAndNameFromActionId(bladeburner.action); return bladeburner.getTypeAndNameFromActionId(bladeburner.action);
}, },
getActionTime: function (type: any = "", name: any = ""): number { getActionTime: function (_type: unknown, _name: unknown): number {
const type = helper.string("getActionTime", "type", _type);
const name = helper.string("getActionTime", "name", _name);
helper.updateDynamicRam("getActionTime", getRamCost(player, "bladeburner", "getActionTime")); helper.updateDynamicRam("getActionTime", getRamCost(player, "bladeburner", "getActionTime"));
checkBladeburnerAccess("getActionTime"); checkBladeburnerAccess("getActionTime");
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
@ -133,7 +139,9 @@ export function NetscriptBladeburner(
throw helper.makeRuntimeErrorMsg("bladeburner.getActionTime", e); throw helper.makeRuntimeErrorMsg("bladeburner.getActionTime", e);
} }
}, },
getActionEstimatedSuccessChance: function (type: any = "", name: any = ""): [number, number] { getActionEstimatedSuccessChance: function (_type: unknown, _name: unknown): [number, number] {
const type = helper.string("getActionEstimatedSuccessChance", "type", _type);
const name = helper.string("getActionEstimatedSuccessChance", "name", _name);
helper.updateDynamicRam( helper.updateDynamicRam(
"getActionEstimatedSuccessChance", "getActionEstimatedSuccessChance",
getRamCost(player, "bladeburner", "getActionEstimatedSuccessChance"), getRamCost(player, "bladeburner", "getActionEstimatedSuccessChance"),
@ -147,7 +155,10 @@ export function NetscriptBladeburner(
throw helper.makeRuntimeErrorMsg("bladeburner.getActionEstimatedSuccessChance", e); throw helper.makeRuntimeErrorMsg("bladeburner.getActionEstimatedSuccessChance", e);
} }
}, },
getActionRepGain: function (type: any = "", name: any = "", level: any): number { getActionRepGain: function (_type: unknown, _name: unknown, _level: unknown): number {
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")); helper.updateDynamicRam("getActionRepGain", getRamCost(player, "bladeburner", "getActionRepGain"));
checkBladeburnerAccess("getActionRepGain"); checkBladeburnerAccess("getActionRepGain");
const action = getBladeburnerActionObject("getActionRepGain", type, name); const action = getBladeburnerActionObject("getActionRepGain", type, name);
@ -160,7 +171,9 @@ export function NetscriptBladeburner(
return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank; return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank;
}, },
getActionCountRemaining: function (type: any = "", name: any = ""): number { getActionCountRemaining: function (_type: unknown, _name: unknown): number {
const type = helper.string("getActionCountRemaining", "type", _type);
const name = helper.string("getActionCountRemaining", "name", _name);
helper.updateDynamicRam("getActionCountRemaining", getRamCost(player, "bladeburner", "getActionCountRemaining")); helper.updateDynamicRam("getActionCountRemaining", getRamCost(player, "bladeburner", "getActionCountRemaining"));
checkBladeburnerAccess("getActionCountRemaining"); checkBladeburnerAccess("getActionCountRemaining");
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
@ -171,31 +184,43 @@ export function NetscriptBladeburner(
throw helper.makeRuntimeErrorMsg("bladeburner.getActionCountRemaining", e); throw helper.makeRuntimeErrorMsg("bladeburner.getActionCountRemaining", e);
} }
}, },
getActionMaxLevel: function (type: any = "", name: any = ""): number { getActionMaxLevel: function (_type: unknown, _name: unknown): number {
const type = helper.string("getActionMaxLevel", "type", _type);
const name = helper.string("getActionMaxLevel", "name", _name);
helper.updateDynamicRam("getActionMaxLevel", getRamCost(player, "bladeburner", "getActionMaxLevel")); helper.updateDynamicRam("getActionMaxLevel", getRamCost(player, "bladeburner", "getActionMaxLevel"));
checkBladeburnerAccess("getActionMaxLevel"); checkBladeburnerAccess("getActionMaxLevel");
const action = getBladeburnerActionObject("getActionMaxLevel", type, name); const action = getBladeburnerActionObject("getActionMaxLevel", type, name);
return action.maxLevel; return action.maxLevel;
}, },
getActionCurrentLevel: function (type: any = "", name: any = ""): number { getActionCurrentLevel: function (_type: unknown, _name: unknown): number {
const type = helper.string("getActionCurrentLevel", "type", _type);
const name = helper.string("getActionCurrentLevel", "name", _name);
helper.updateDynamicRam("getActionCurrentLevel", getRamCost(player, "bladeburner", "getActionCurrentLevel")); helper.updateDynamicRam("getActionCurrentLevel", getRamCost(player, "bladeburner", "getActionCurrentLevel"));
checkBladeburnerAccess("getActionCurrentLevel"); checkBladeburnerAccess("getActionCurrentLevel");
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name); const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
return action.level; return action.level;
}, },
getActionAutolevel: function (type: any = "", name: any = ""): boolean { getActionAutolevel: function (_type: unknown, _name: unknown): boolean {
const type = helper.string("getActionAutolevel", "type", _type);
const name = helper.string("getActionAutolevel", "name", _name);
helper.updateDynamicRam("getActionAutolevel", getRamCost(player, "bladeburner", "getActionAutolevel")); helper.updateDynamicRam("getActionAutolevel", getRamCost(player, "bladeburner", "getActionAutolevel"));
checkBladeburnerAccess("getActionAutolevel"); checkBladeburnerAccess("getActionAutolevel");
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name); const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
return action.autoLevel; return action.autoLevel;
}, },
setActionAutolevel: function (type: any = "", name: any = "", autoLevel: any = true): void { setActionAutolevel: function (_type: unknown, _name: unknown, _autoLevel: unknown = true): void {
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")); helper.updateDynamicRam("setActionAutolevel", getRamCost(player, "bladeburner", "setActionAutolevel"));
checkBladeburnerAccess("setActionAutolevel"); checkBladeburnerAccess("setActionAutolevel");
const action = getBladeburnerActionObject("setActionAutolevel", type, name); const action = getBladeburnerActionObject("setActionAutolevel", type, name);
action.autoLevel = autoLevel; action.autoLevel = autoLevel;
}, },
setActionLevel: function (type: any = "", name: any = "", level: any = 1): void { setActionLevel: function (_type: unknown, _name: unknown, _level: unknown = 1): void {
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")); helper.updateDynamicRam("setActionLevel", getRamCost(player, "bladeburner", "setActionLevel"));
checkBladeburnerAccess("setActionLevel"); checkBladeburnerAccess("setActionLevel");
const action = getBladeburnerActionObject("setActionLevel", type, name); const action = getBladeburnerActionObject("setActionLevel", type, name);
@ -221,7 +246,8 @@ export function NetscriptBladeburner(
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.skillPoints; return bladeburner.skillPoints;
}, },
getSkillLevel: function (skillName: any = ""): number { getSkillLevel: function (_skillName: unknown): number {
const skillName = helper.string("getSkillLevel", "skillName", _skillName);
helper.updateDynamicRam("getSkillLevel", getRamCost(player, "bladeburner", "getSkillLevel")); helper.updateDynamicRam("getSkillLevel", getRamCost(player, "bladeburner", "getSkillLevel"));
checkBladeburnerAccess("getSkillLevel"); checkBladeburnerAccess("getSkillLevel");
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
@ -232,7 +258,8 @@ export function NetscriptBladeburner(
throw helper.makeRuntimeErrorMsg("bladeburner.getSkillLevel", e); throw helper.makeRuntimeErrorMsg("bladeburner.getSkillLevel", e);
} }
}, },
getSkillUpgradeCost: function (skillName: any = ""): number { getSkillUpgradeCost: function (_skillName: unknown): number {
const skillName = helper.string("getSkillUpgradeCost", "skillName", _skillName);
helper.updateDynamicRam("getSkillUpgradeCost", getRamCost(player, "bladeburner", "getSkillUpgradeCost")); helper.updateDynamicRam("getSkillUpgradeCost", getRamCost(player, "bladeburner", "getSkillUpgradeCost"));
checkBladeburnerAccess("getSkillUpgradeCost"); checkBladeburnerAccess("getSkillUpgradeCost");
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
@ -243,7 +270,8 @@ export function NetscriptBladeburner(
throw helper.makeRuntimeErrorMsg("bladeburner.getSkillUpgradeCost", e); throw helper.makeRuntimeErrorMsg("bladeburner.getSkillUpgradeCost", e);
} }
}, },
upgradeSkill: function (skillName: any): boolean { upgradeSkill: function (_skillName: unknown): boolean {
const skillName = helper.string("upgradeSkill", "skillName", _skillName);
helper.updateDynamicRam("upgradeSkill", getRamCost(player, "bladeburner", "upgradeSkill")); helper.updateDynamicRam("upgradeSkill", getRamCost(player, "bladeburner", "upgradeSkill"));
checkBladeburnerAccess("upgradeSkill"); checkBladeburnerAccess("upgradeSkill");
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
@ -254,7 +282,9 @@ export function NetscriptBladeburner(
throw helper.makeRuntimeErrorMsg("bladeburner.upgradeSkill", e); throw helper.makeRuntimeErrorMsg("bladeburner.upgradeSkill", e);
} }
}, },
getTeamSize: function (type: any = "", name: any = ""): number { getTeamSize: function (_type: unknown, _name: unknown): number {
const type = helper.string("getTeamSize", "type", _type);
const name = helper.string("getTeamSize", "name", _name);
helper.updateDynamicRam("getTeamSize", getRamCost(player, "bladeburner", "getTeamSize")); helper.updateDynamicRam("getTeamSize", getRamCost(player, "bladeburner", "getTeamSize"));
checkBladeburnerAccess("getTeamSize"); checkBladeburnerAccess("getTeamSize");
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
@ -265,7 +295,10 @@ export function NetscriptBladeburner(
throw helper.makeRuntimeErrorMsg("bladeburner.getTeamSize", e); throw helper.makeRuntimeErrorMsg("bladeburner.getTeamSize", e);
} }
}, },
setTeamSize: function (type: any = "", name: any = "", size: any): number { setTeamSize: function (_type: unknown, _name: unknown, _size: unknown): number {
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")); helper.updateDynamicRam("setTeamSize", getRamCost(player, "bladeburner", "setTeamSize"));
checkBladeburnerAccess("setTeamSize"); checkBladeburnerAccess("setTeamSize");
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
@ -276,7 +309,8 @@ export function NetscriptBladeburner(
throw helper.makeRuntimeErrorMsg("bladeburner.setTeamSize", e); throw helper.makeRuntimeErrorMsg("bladeburner.setTeamSize", e);
} }
}, },
getCityEstimatedPopulation: function (cityName: any): number { getCityEstimatedPopulation: function (_cityName: unknown): number {
const cityName = helper.string("getCityEstimatedPopulation", "cityName", _cityName);
helper.updateDynamicRam( helper.updateDynamicRam(
"getCityEstimatedPopulation", "getCityEstimatedPopulation",
getRamCost(player, "bladeburner", "getCityEstimatedPopulation"), getRamCost(player, "bladeburner", "getCityEstimatedPopulation"),
@ -287,7 +321,8 @@ export function NetscriptBladeburner(
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.cities[cityName].popEst; return bladeburner.cities[cityName].popEst;
}, },
getCityCommunities: function (cityName: any): number { getCityCommunities: function (_cityName: unknown): number {
const cityName = helper.string("getCityCommunities", "cityName", _cityName);
helper.updateDynamicRam("getCityCommunities", getRamCost(player, "bladeburner", "getCityCommunities")); helper.updateDynamicRam("getCityCommunities", getRamCost(player, "bladeburner", "getCityCommunities"));
checkBladeburnerAccess("getCityCommunities"); checkBladeburnerAccess("getCityCommunities");
checkBladeburnerCity("getCityCommunities", cityName); checkBladeburnerCity("getCityCommunities", cityName);
@ -295,7 +330,8 @@ export function NetscriptBladeburner(
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.cities[cityName].comms; return bladeburner.cities[cityName].comms;
}, },
getCityChaos: function (cityName: any): number { getCityChaos: function (_cityName: unknown): number {
const cityName = helper.string("getCityChaos", "cityName", _cityName);
helper.updateDynamicRam("getCityChaos", getRamCost(player, "bladeburner", "getCityChaos")); helper.updateDynamicRam("getCityChaos", getRamCost(player, "bladeburner", "getCityChaos"));
checkBladeburnerAccess("getCityChaos"); checkBladeburnerAccess("getCityChaos");
checkBladeburnerCity("getCityChaos", cityName); checkBladeburnerCity("getCityChaos", cityName);
@ -310,13 +346,14 @@ export function NetscriptBladeburner(
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.city; return bladeburner.city;
}, },
switchCity: function (cityName: any): boolean { switchCity: function (_cityName: unknown): boolean {
const cityName = helper.string("switchCity", "cityName", _cityName);
helper.updateDynamicRam("switchCity", getRamCost(player, "bladeburner", "switchCity")); helper.updateDynamicRam("switchCity", getRamCost(player, "bladeburner", "switchCity"));
checkBladeburnerAccess("switchCity"); checkBladeburnerAccess("switchCity");
checkBladeburnerCity("switchCity", cityName); checkBladeburnerCity("switchCity", cityName);
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return (bladeburner.city = cityName); return bladeburner.city === cityName;
}, },
getStamina: function (): [number, number] { getStamina: function (): [number, number] {
helper.updateDynamicRam("getStamina", getRamCost(player, "bladeburner", "getStamina")); helper.updateDynamicRam("getStamina", getRamCost(player, "bladeburner", "getStamina"));
@ -365,7 +402,7 @@ export function NetscriptBladeburner(
checkBladeburnerAccess("getBonusTime"); checkBladeburnerAccess("getBonusTime");
const bladeburner = player.bladeburner; const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return (Math.round(bladeburner.storedCycles / 5))*1000; return Math.round(bladeburner.storedCycles / 5) * 1000;
}, },
}; };
} }

@ -4,14 +4,14 @@ import { IPlayer } from "../PersonObjects/IPlayer";
import { getRamCost } from "../Netscript/RamCostGenerator"; import { getRamCost } from "../Netscript/RamCostGenerator";
import { is2DArray } from "../utils/helpers/is2DArray"; import { is2DArray } from "../utils/helpers/is2DArray";
import { CodingContract } from "../CodingContracts"; import { CodingContract } from "../CodingContracts";
import { CodingContract as ICodingContract } from "../ScriptEditor/NetscriptDefinitions"; import { CodingAttemptOptions, CodingContract as ICodingContract } from "../ScriptEditor/NetscriptDefinitions";
export function NetscriptCodingContract( export function NetscriptCodingContract(
player: IPlayer, player: IPlayer,
workerScript: WorkerScript, workerScript: WorkerScript,
helper: INetscriptHelper, helper: INetscriptHelper,
): ICodingContract { ): ICodingContract {
const getCodingContract = function (func: any, hostname: any, filename: any): CodingContract { const getCodingContract = function (func: string, hostname: string, filename: string): CodingContract {
const server = helper.getServer(hostname, func); const server = helper.getServer(hostname, func);
const contract = server.getContract(filename); const contract = server.getContract(filename);
if (contract == null) { if (contract == null) {
@ -27,10 +27,12 @@ export function NetscriptCodingContract(
return { return {
attempt: function ( attempt: function (
answer: any, answer: any,
filename: any, _filename: unknown,
hostname: any = workerScript.hostname, _hostname: unknown = workerScript.hostname,
{ returnReward }: any = {}, { returnReward }: CodingAttemptOptions = { returnReward: false },
): boolean | string { ): boolean | string {
const filename = helper.string("attempt", "filename", _filename);
const hostname = helper.string("attempt", "hostname", _hostname);
helper.updateDynamicRam("attempt", getRamCost(player, "codingcontract", "attempt")); helper.updateDynamicRam("attempt", getRamCost(player, "codingcontract", "attempt"));
const contract = getCodingContract("attempt", hostname, filename); const contract = getCodingContract("attempt", hostname, filename);
@ -53,7 +55,10 @@ export function NetscriptCodingContract(
const serv = helper.getServer(hostname, "codingcontract.attempt"); const serv = helper.getServer(hostname, "codingcontract.attempt");
if (contract.isSolution(answer)) { if (contract.isSolution(answer)) {
const reward = player.gainCodingContractReward(creward, contract.getDifficulty()); const reward = player.gainCodingContractReward(creward, contract.getDifficulty());
workerScript.log("codingcontract.attempt", () => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`); workerScript.log(
"codingcontract.attempt",
() => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`,
);
serv.removeContract(filename); serv.removeContract(filename);
return returnReward ? reward : true; return returnReward ? reward : true;
} else { } else {
@ -68,7 +73,8 @@ export function NetscriptCodingContract(
workerScript.log( workerScript.log(
"codingcontract.attempt", "codingcontract.attempt",
() => () =>
`Coding Contract attempt '${filename}' failed. ${contract.getMaxNumTries() - contract.tries `Coding Contract attempt '${filename}' failed. ${
contract.getMaxNumTries() - contract.tries
} attempts remaining.`, } attempts remaining.`,
); );
} }
@ -76,12 +82,16 @@ export function NetscriptCodingContract(
return returnReward ? "" : false; return returnReward ? "" : false;
} }
}, },
getContractType: function (filename: any, hostname: any = workerScript.hostname): string { getContractType: function (_filename: unknown, _hostname: unknown = workerScript.hostname): string {
const filename = helper.string("getContractType", "filename", _filename);
const hostname = helper.string("getContractType", "hostname", _hostname);
helper.updateDynamicRam("getContractType", getRamCost(player, "codingcontract", "getContractType")); helper.updateDynamicRam("getContractType", getRamCost(player, "codingcontract", "getContractType"));
const contract = getCodingContract("getContractType", hostname, filename); const contract = getCodingContract("getContractType", hostname, filename);
return contract.getType(); return contract.getType();
}, },
getData: function (filename: any, hostname: any = workerScript.hostname): any { getData: function (_filename: unknown, _hostname: unknown = workerScript.hostname): any {
const filename = helper.string("getContractType", "filename", _filename);
const hostname = helper.string("getContractType", "hostname", _hostname);
helper.updateDynamicRam("getData", getRamCost(player, "codingcontract", "getData")); helper.updateDynamicRam("getData", getRamCost(player, "codingcontract", "getData"));
const contract = getCodingContract("getData", hostname, filename); const contract = getCodingContract("getData", hostname, filename);
const data = contract.getData(); const data = contract.getData();
@ -101,12 +111,16 @@ export function NetscriptCodingContract(
return data; return data;
} }
}, },
getDescription: function (filename: any, hostname: any = workerScript.hostname): string { getDescription: function (_filename: unknown, _hostname: unknown = workerScript.hostname): string {
const filename = helper.string("getDescription", "filename", _filename);
const hostname = helper.string("getDescription", "hostname", _hostname);
helper.updateDynamicRam("getDescription", getRamCost(player, "codingcontract", "getDescription")); helper.updateDynamicRam("getDescription", getRamCost(player, "codingcontract", "getDescription"));
const contract = getCodingContract("getDescription", hostname, filename); const contract = getCodingContract("getDescription", hostname, filename);
return contract.getDescription(); return contract.getDescription();
}, },
getNumTriesRemaining: function (filename: any, hostname: any = workerScript.hostname): number { getNumTriesRemaining: function (_filename: unknown, _hostname: unknown = workerScript.hostname): number {
const filename = helper.string("getNumTriesRemaining", "filename", _filename);
const hostname = helper.string("getNumTriesRemaining", "hostname", _hostname);
helper.updateDynamicRam("getNumTriesRemaining", getRamCost(player, "codingcontract", "getNumTriesRemaining")); helper.updateDynamicRam("getNumTriesRemaining", getRamCost(player, "codingcontract", "getNumTriesRemaining"));
const contract = getCodingContract("getNumTriesRemaining", hostname, filename); const contract = getCodingContract("getNumTriesRemaining", hostname, filename);
return contract.getMaxNumTries() - contract.tries; return contract.getMaxNumTries() - contract.tries;

@ -21,7 +21,7 @@ import {
Division as NSDivision, Division as NSDivision,
WarehouseAPI, WarehouseAPI,
OfficeAPI, OfficeAPI,
InvestmentOffer InvestmentOffer,
} from "../ScriptEditor/NetscriptDefinitions"; } from "../ScriptEditor/NetscriptDefinitions";
import { import {
@ -100,8 +100,8 @@ export function NetscriptCorporation(
return upgrade[1]; return upgrade[1];
} }
function getUpgradeLevel(aupgradeName: string): number { function getUpgradeLevel(_upgradeName: string): number {
const upgradeName = helper.string("levelUpgrade", "upgradeName", aupgradeName); const upgradeName = helper.string("levelUpgrade", "upgradeName", _upgradeName);
const corporation = getCorporation(); const corporation = getCorporation();
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName); const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`); if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
@ -109,8 +109,8 @@ export function NetscriptCorporation(
return corporation.upgrades[upgN]; return corporation.upgrades[upgN];
} }
function getUpgradeLevelCost(aupgradeName: string): number { function getUpgradeLevelCost(_upgradeName: string): number {
const upgradeName = helper.string("levelUpgrade", "upgradeName", aupgradeName); const upgradeName = helper.string("levelUpgrade", "upgradeName", _upgradeName);
const corporation = getCorporation(); const corporation = getCorporation();
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName); const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`); if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
@ -135,11 +135,15 @@ export function NetscriptCorporation(
function getInvestmentOffer(): InvestmentOffer { function getInvestmentOffer(): InvestmentOffer {
const corporation = getCorporation(); const corporation = getCorporation();
if (corporation.fundingRound >= CorporationConstants.FundingRoundShares.length || corporation.fundingRound >= CorporationConstants.FundingRoundMultiplier.length || corporation.public) if (
corporation.fundingRound >= CorporationConstants.FundingRoundShares.length ||
corporation.fundingRound >= CorporationConstants.FundingRoundMultiplier.length ||
corporation.public
)
return { return {
funds: 0, funds: 0,
shares: 0, shares: 0,
round: corporation.fundingRound + 1 // Make more readable round: corporation.fundingRound + 1, // Make more readable
}; // Don't throw an error here, no reason to have a second function to check if you can get investment. }; // Don't throw an error here, no reason to have a second function to check if you can get investment.
const val = corporation.determineValuation(); const val = corporation.determineValuation();
const percShares = CorporationConstants.FundingRoundShares[corporation.fundingRound]; const percShares = CorporationConstants.FundingRoundShares[corporation.fundingRound];
@ -149,13 +153,18 @@ export function NetscriptCorporation(
return { return {
funds: funding, funds: funding,
shares: investShares, shares: investShares,
round: corporation.fundingRound + 1 // Make more readable round: corporation.fundingRound + 1, // Make more readable
}; };
} }
function acceptInvestmentOffer(): boolean { function acceptInvestmentOffer(): boolean {
const corporation = getCorporation(); const corporation = getCorporation();
if (corporation.fundingRound >= CorporationConstants.FundingRoundShares.length || corporation.fundingRound >= CorporationConstants.FundingRoundMultiplier.length || corporation.public) return false; if (
corporation.fundingRound >= CorporationConstants.FundingRoundShares.length ||
corporation.fundingRound >= CorporationConstants.FundingRoundMultiplier.length ||
corporation.public
)
return false;
const val = corporation.determineValuation(); const val = corporation.determineValuation();
const percShares = CorporationConstants.FundingRoundShares[corporation.fundingRound]; const percShares = CorporationConstants.FundingRoundShares[corporation.fundingRound];
const roundMultiplier = CorporationConstants.FundingRoundMultiplier[corporation.fundingRound]; const roundMultiplier = CorporationConstants.FundingRoundMultiplier[corporation.fundingRound];
@ -181,7 +190,6 @@ export function NetscriptCorporation(
return true; return true;
} }
function getResearchCost(division: IIndustry, researchName: string): number { function getResearchCost(division: IIndustry, researchName: string): number {
const researchTree = IndustryResearchTrees[division.type]; const researchTree = IndustryResearchTrees[division.type];
if (researchTree === undefined) throw new Error(`No research tree for industry '${division.type}'`); if (researchTree === undefined) throw new Error(`No research tree for industry '${division.type}'`);
@ -192,17 +200,18 @@ export function NetscriptCorporation(
} }
function hasResearched(division: IIndustry, researchName: string): boolean { function hasResearched(division: IIndustry, researchName: string): boolean {
return division.researched[researchName] === undefined ? false : division.researched[researchName] as boolean; return division.researched[researchName] === undefined ? false : (division.researched[researchName] as boolean);
} }
function bribe(factionName: string, amountCash: number, amountShares: number): boolean { function bribe(factionName: string, amountCash: number, amountShares: number): boolean {
if (!player.factions.includes(factionName)) throw new Error("Invalid faction name"); if (!player.factions.includes(factionName)) throw new Error("Invalid faction name");
if (isNaN(amountCash) || amountCash < 0 || isNaN(amountShares) || amountShares < 0) throw new Error("Invalid value for amount field! Must be numeric, grater than 0."); if (isNaN(amountCash) || amountCash < 0 || isNaN(amountShares) || amountShares < 0)
throw new Error("Invalid value for amount field! Must be numeric, grater than 0.");
const corporation = getCorporation(); const corporation = getCorporation();
if (corporation.funds < amountCash) return false; if (corporation.funds < amountCash) return false;
if (corporation.numShares < amountShares) return false; if (corporation.numShares < amountShares) return false;
const faction = Factions[factionName] const faction = Factions[factionName];
const info = faction.getInfo(); const info = faction.getInfo();
if (!info.offersWork()) return false; if (!info.offersWork()) return false;
if (player.hasGangWith(factionName)) return false; if (player.hasGangWith(factionName)) return false;
@ -221,14 +230,14 @@ export function NetscriptCorporation(
return corporation; return corporation;
} }
function getDivision(divisionName: any): IIndustry { function getDivision(divisionName: string): IIndustry {
const corporation = getCorporation(); const corporation = getCorporation();
const division = corporation.divisions.find((div) => div.name === divisionName); const division = corporation.divisions.find((div) => div.name === divisionName);
if (division === undefined) throw new Error(`No division named '${divisionName}'`); if (division === undefined) throw new Error(`No division named '${divisionName}'`);
return division; return division;
} }
function getOffice(divisionName: any, cityName: any): OfficeSpace { function getOffice(divisionName: string, cityName: string): OfficeSpace {
const division = getDivision(divisionName); const division = getDivision(divisionName);
if (!(cityName in division.offices)) throw new Error(`Invalid city name '${cityName}'`); if (!(cityName in division.offices)) throw new Error(`Invalid city name '${cityName}'`);
const office = division.offices[cityName]; const office = division.offices[cityName];
@ -236,7 +245,7 @@ export function NetscriptCorporation(
return office; return office;
} }
function getWarehouse(divisionName: any, cityName: any): Warehouse { function getWarehouse(divisionName: string, cityName: string): Warehouse {
const division = getDivision(divisionName); const division = getDivision(divisionName);
if (!(cityName in division.warehouses)) throw new Error(`Invalid city name '${cityName}'`); if (!(cityName in division.warehouses)) throw new Error(`Invalid city name '${cityName}'`);
const warehouse = division.warehouses[cityName]; const warehouse = division.warehouses[cityName];
@ -244,7 +253,7 @@ export function NetscriptCorporation(
return warehouse; return warehouse;
} }
function getMaterial(divisionName: any, cityName: any, materialName: any): Material { function getMaterial(divisionName: string, cityName: string, materialName: string): Material {
const warehouse = getWarehouse(divisionName, cityName); const warehouse = getWarehouse(divisionName, cityName);
const matName = (materialName as string).replace(/ /g, ""); const matName = (materialName as string).replace(/ /g, "");
const material = warehouse.materials[matName]; const material = warehouse.materials[matName];
@ -252,14 +261,14 @@ export function NetscriptCorporation(
return material; return material;
} }
function getProduct(divisionName: any, productName: any): Product { function getProduct(divisionName: string, productName: string): Product {
const division = getDivision(divisionName); const division = getDivision(divisionName);
const product = division.products[productName]; const product = division.products[productName];
if (product === undefined) throw new Error(`Invalid product name: '${productName}'`); if (product === undefined) throw new Error(`Invalid product name: '${productName}'`);
return product; return product;
} }
function getEmployee(divisionName: any, cityName: any, employeeName: any): Employee { function getEmployee(divisionName: string, cityName: string, employeeName: string): Employee {
const office = getOffice(divisionName, cityName); const office = getOffice(divisionName, cityName);
const employee = office.employees.find((e) => e.name === employeeName); const employee = office.employees.find((e) => e.name === employeeName);
if (employee === undefined) throw new Error(`Invalid employee name: '${employeeName}'`); if (employee === undefined) throw new Error(`Invalid employee name: '${employeeName}'`);
@ -302,40 +311,40 @@ export function NetscriptCorporation(
checkAccess("getPurchaseWarehouseCost", 7); checkAccess("getPurchaseWarehouseCost", 7);
return CorporationConstants.WarehouseInitialCost; return CorporationConstants.WarehouseInitialCost;
}, },
getUpgradeWarehouseCost: function (adivisionName: any, acityName: any): number { getUpgradeWarehouseCost: function (_divisionName: unknown, _cityName: unknown): number {
checkAccess("upgradeWarehouse", 7); checkAccess("upgradeWarehouse", 7);
const divisionName = helper.string("getUpgradeWarehouseCost", "divisionName", adivisionName); const divisionName = helper.string("getUpgradeWarehouseCost", "divisionName", _divisionName);
const cityName = helper.string("getUpgradeWarehouseCost", "cityName", acityName); const cityName = helper.city("getUpgradeWarehouseCost", "cityName", _cityName);
const warehouse = getWarehouse(divisionName, cityName); const warehouse = getWarehouse(divisionName, cityName);
return CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, warehouse.level + 1); return CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, warehouse.level + 1);
}, },
hasWarehouse: function (adivisionName: any, acityName: any): boolean { hasWarehouse: function (_divisionName: unknown, _cityName: unknown): boolean {
checkAccess("hasWarehouse", 7); checkAccess("hasWarehouse", 7);
const divisionName = helper.string("getWarehouse", "divisionName", adivisionName); const divisionName = helper.string("getWarehouse", "divisionName", _divisionName);
const cityName = helper.string("getWarehouse", "cityName", acityName); const cityName = helper.city("getWarehouse", "cityName", _cityName);
const division = getDivision(divisionName); const division = getDivision(divisionName);
if (!(cityName in division.warehouses)) throw new Error(`Invalid city name '${cityName}'`); if (!(cityName in division.warehouses)) throw new Error(`Invalid city name '${cityName}'`);
const warehouse = division.warehouses[cityName]; const warehouse = division.warehouses[cityName];
return warehouse !== 0; return warehouse !== 0;
}, },
getWarehouse: function (adivisionName: any, acityName: any): NSWarehouse { getWarehouse: function (_divisionName: unknown, _cityName: unknown): NSWarehouse {
checkAccess("getWarehouse", 7); checkAccess("getWarehouse", 7);
const divisionName = helper.string("getWarehouse", "divisionName", adivisionName); const divisionName = helper.string("getWarehouse", "divisionName", _divisionName);
const cityName = helper.string("getWarehouse", "cityName", acityName); const cityName = helper.city("getWarehouse", "cityName", _cityName);
const warehouse = getWarehouse(divisionName, cityName); const warehouse = getWarehouse(divisionName, cityName);
return { return {
level: warehouse.level, level: warehouse.level,
loc: warehouse.loc, loc: warehouse.loc,
size: warehouse.size, size: warehouse.size,
sizeUsed: warehouse.sizeUsed, sizeUsed: warehouse.sizeUsed,
smartSupplyEnabled: warehouse.smartSupplyEnabled smartSupplyEnabled: warehouse.smartSupplyEnabled,
}; };
}, },
getMaterial: function (adivisionName: any, acityName: any, amaterialName: any): NSMaterial { getMaterial: function (_divisionName: unknown, _cityName: unknown, _materialName: unknown): NSMaterial {
checkAccess("getMaterial", 7); checkAccess("getMaterial", 7);
const divisionName = helper.string("getMaterial", "divisionName", adivisionName); const divisionName = helper.string("getMaterial", "divisionName", _divisionName);
const cityName = helper.string("getMaterial", "cityName", acityName); const cityName = helper.city("getMaterial", "cityName", _cityName);
const materialName = helper.string("getMaterial", "materialName", amaterialName); const materialName = helper.string("getMaterial", "materialName", _materialName);
const material = getMaterial(divisionName, cityName, materialName); const material = getMaterial(divisionName, cityName, materialName);
return { return {
name: material.name, name: material.name,
@ -345,10 +354,10 @@ export function NetscriptCorporation(
sell: material.sll, sell: material.sll,
}; };
}, },
getProduct: function (adivisionName: any, aproductName: any): NSProduct { getProduct: function (_divisionName: unknown, _productName: unknown): NSProduct {
checkAccess("getProduct", 7); checkAccess("getProduct", 7);
const divisionName = helper.string("getProduct", "divisionName", adivisionName); const divisionName = helper.string("getProduct", "divisionName", _divisionName);
const productName = helper.string("getProduct", "productName", aproductName); const productName = helper.string("getProduct", "productName", _productName);
const product = getProduct(divisionName, productName); const product = getProduct(divisionName, productName);
return { return {
name: product.name, name: product.name,
@ -360,220 +369,271 @@ export function NetscriptCorporation(
developmentProgress: product.prog, developmentProgress: product.prog,
}; };
}, },
purchaseWarehouse: function (adivisionName: any, acityName: any): void { purchaseWarehouse: function (_divisionName: unknown, _cityName: unknown): void {
checkAccess("purchaseWarehouse", 7); checkAccess("purchaseWarehouse", 7);
const divisionName = helper.string("purchaseWarehouse", "divisionName", adivisionName); const divisionName = helper.string("purchaseWarehouse", "divisionName", _divisionName);
const cityName = helper.string("purchaseWarehouse", "cityName", acityName); const cityName = helper.city("purchaseWarehouse", "cityName", _cityName);
const corporation = getCorporation(); const corporation = getCorporation();
PurchaseWarehouse(corporation, getDivision(divisionName), cityName); PurchaseWarehouse(corporation, getDivision(divisionName), cityName);
}, },
upgradeWarehouse: function (adivisionName: any, acityName: any): void { upgradeWarehouse: function (_divisionName: unknown, _cityName: unknown): void {
checkAccess("upgradeWarehouse", 7); checkAccess("upgradeWarehouse", 7);
const divisionName = helper.string("upgradeWarehouse", "divisionName", adivisionName); const divisionName = helper.string("upgradeWarehouse", "divisionName", _divisionName);
const cityName = helper.string("upgradeWarehouse", "cityName", acityName); const cityName = helper.city("upgradeWarehouse", "cityName", _cityName);
const corporation = getCorporation(); const corporation = getCorporation();
UpgradeWarehouse(corporation, getDivision(divisionName), getWarehouse(divisionName, cityName)); UpgradeWarehouse(corporation, getDivision(divisionName), getWarehouse(divisionName, cityName));
}, },
sellMaterial: function (adivisionName: any, acityName: any, amaterialName: any, aamt: any, aprice: any): void { sellMaterial: function (
_divisionName: unknown,
_cityName: unknown,
_materialName: unknown,
_amt: unknown,
_price: unknown,
): void {
checkAccess("sellMaterial", 7); checkAccess("sellMaterial", 7);
const divisionName = helper.string("sellMaterial", "divisionName", adivisionName); const divisionName = helper.string("sellMaterial", "divisionName", _divisionName);
const cityName = helper.string("sellMaterial", "cityName", acityName); const cityName = helper.city("sellMaterial", "cityName", _cityName);
const materialName = helper.string("sellMaterial", "materialName", amaterialName); const materialName = helper.string("sellMaterial", "materialName", _materialName);
const amt = helper.string("sellMaterial", "amt", aamt); const amt = helper.string("sellMaterial", "amt", _amt);
const price = helper.string("sellMaterial", "price", aprice); const price = helper.string("sellMaterial", "price", _price);
const material = getMaterial(divisionName, cityName, materialName); const material = getMaterial(divisionName, cityName, materialName);
SellMaterial(material, amt, price); SellMaterial(material, amt, price);
}, },
sellProduct: function ( sellProduct: function (
adivisionName: any, _divisionName: unknown,
acityName: any, _cityName: unknown,
aproductName: any, _productName: unknown,
aamt: any, _amt: unknown,
aprice: any, _price: unknown,
aall: any, _all: unknown,
): void { ): void {
checkAccess("sellProduct", 7); checkAccess("sellProduct", 7);
const divisionName = helper.string("sellProduct", "divisionName", adivisionName); const divisionName = helper.string("sellProduct", "divisionName", _divisionName);
const cityName = helper.string("sellProduct", "cityName", acityName); const cityName = helper.city("sellProduct", "cityName", _cityName);
const productName = helper.string("sellProduct", "productName", aproductName); const productName = helper.string("sellProduct", "productName", _productName);
const amt = helper.string("sellProduct", "amt", aamt); const amt = helper.string("sellProduct", "amt", _amt);
const price = helper.string("sellProduct", "price", aprice); const price = helper.string("sellProduct", "price", _price);
const all = helper.boolean(aall); const all = helper.boolean(_all);
const product = getProduct(divisionName, productName); const product = getProduct(divisionName, productName);
SellProduct(product, cityName, amt, price, all); SellProduct(product, cityName, amt, price, all);
}, },
discontinueProduct: function (adivisionName: any, aproductName: any): void { discontinueProduct: function (_divisionName: unknown, _productName: unknown): void {
checkAccess("discontinueProduct", 7); checkAccess("discontinueProduct", 7);
const divisionName = helper.string("discontinueProduct", "divisionName", adivisionName); const divisionName = helper.string("discontinueProduct", "divisionName", _divisionName);
const productName = helper.string("discontinueProduct", "productName", aproductName); const productName = helper.string("discontinueProduct", "productName", _productName);
getDivision(divisionName).discontinueProduct(getProduct(divisionName, productName)); getDivision(divisionName).discontinueProduct(getProduct(divisionName, productName));
}, },
setSmartSupply: function (adivisionName: any, acityName: any, aenabled: any): void { setSmartSupply: function (_divisionName: unknown, _cityName: unknown, _enabled: unknown): void {
checkAccess("setSmartSupply", 7); checkAccess("setSmartSupply", 7);
const divisionName = helper.string("setSmartSupply", "divisionName", adivisionName); const divisionName = helper.string("setSmartSupply", "divisionName", _divisionName);
const cityName = helper.string("sellProduct", "cityName", acityName); const cityName = helper.city("sellProduct", "cityName", _cityName);
const enabled = helper.boolean(aenabled); const enabled = helper.boolean(_enabled);
const warehouse = getWarehouse(divisionName, cityName); const warehouse = getWarehouse(divisionName, cityName);
if (!hasUnlockUpgrade("Smart Supply")) if (!hasUnlockUpgrade("Smart Supply"))
throw helper.makeRuntimeErrorMsg(`corporation.setSmartSupply`, `You have not purchased the Smart Supply upgrade!`); throw helper.makeRuntimeErrorMsg(
`corporation.setSmartSupply`,
`You have not purchased the Smart Supply upgrade!`,
);
SetSmartSupply(warehouse, enabled); SetSmartSupply(warehouse, enabled);
}, },
setSmartSupplyUseLeftovers: function (adivisionName: any, acityName: any, amaterialName: any, aenabled: any): void { setSmartSupplyUseLeftovers: function (
_divisionName: unknown,
_cityName: unknown,
_materialName: unknown,
_enabled: unknown,
): void {
checkAccess("setSmartSupplyUseLeftovers", 7); checkAccess("setSmartSupplyUseLeftovers", 7);
const divisionName = helper.string("setSmartSupply", "divisionName", adivisionName); const divisionName = helper.string("setSmartSupply", "divisionName", _divisionName);
const cityName = helper.string("sellProduct", "cityName", acityName); const cityName = helper.city("sellProduct", "cityName", _cityName);
const materialName = helper.string("sellProduct", "materialName", amaterialName); const materialName = helper.string("sellProduct", "materialName", _materialName);
const enabled = helper.boolean(aenabled); const enabled = helper.boolean(_enabled);
const warehouse = getWarehouse(divisionName, cityName); const warehouse = getWarehouse(divisionName, cityName);
const material = getMaterial(divisionName, cityName, materialName); const material = getMaterial(divisionName, cityName, materialName);
if (!hasUnlockUpgrade("Smart Supply")) if (!hasUnlockUpgrade("Smart Supply"))
throw helper.makeRuntimeErrorMsg(`corporation.setSmartSupply`, `You have not purchased the Smart Supply upgrade!`); throw helper.makeRuntimeErrorMsg(
`corporation.setSmartSupply`,
`You have not purchased the Smart Supply upgrade!`,
);
SetSmartSupplyUseLeftovers(warehouse, material, enabled); SetSmartSupplyUseLeftovers(warehouse, material, enabled);
}, },
buyMaterial: function (adivisionName: any, acityName: any, amaterialName: any, aamt: any): void { buyMaterial: function (_divisionName: unknown, _cityName: unknown, _materialName: unknown, _amt: unknown): void {
checkAccess("buyMaterial", 7); checkAccess("buyMaterial", 7);
const divisionName = helper.string("buyMaterial", "divisionName", adivisionName); const divisionName = helper.string("buyMaterial", "divisionName", _divisionName);
const cityName = helper.string("buyMaterial", "cityName", acityName); const cityName = helper.city("buyMaterial", "cityName", _cityName);
const materialName = helper.string("buyMaterial", "materialName", amaterialName); const materialName = helper.string("buyMaterial", "materialName", _materialName);
const amt = helper.number("buyMaterial", "amt", aamt); const amt = helper.number("buyMaterial", "amt", _amt);
if (amt < 0) throw new Error("Invalid value for amount field! Must be numeric and greater than 0"); if (amt < 0) throw new Error("Invalid value for amount field! Must be numeric and greater than 0");
const material = getMaterial(divisionName, cityName, materialName); const material = getMaterial(divisionName, cityName, materialName);
BuyMaterial(material, amt); BuyMaterial(material, amt);
}, },
bulkPurchase: function (adivisionName: any, acityName: any, amaterialName: any, aamt: any): void { bulkPurchase: function (_divisionName: unknown, _cityName: unknown, _materialName: unknown, _amt: unknown): void {
checkAccess("bulkPurchase", 7); checkAccess("bulkPurchase", 7);
const divisionName = helper.string("bulkPurchase", "divisionName", adivisionName); const divisionName = helper.string("bulkPurchase", "divisionName", _divisionName);
if (!hasResearched(getDivision(adivisionName), "Bulk Purchasing")) throw new Error(`You have not researched Bulk Purchasing in ${divisionName}`) if (!hasResearched(getDivision(divisionName), "Bulk Purchasing"))
throw new Error(`You have not researched Bulk Purchasing in ${divisionName}`);
const corporation = getCorporation(); const corporation = getCorporation();
const cityName = helper.string("bulkPurchase", "cityName", acityName); const cityName = helper.city("bulkPurchase", "cityName", _cityName);
const materialName = helper.string("bulkPurchase", "materialName", amaterialName); const materialName = helper.string("bulkPurchase", "materialName", _materialName);
const amt = helper.number("bulkPurchase", "amt", aamt); const amt = helper.number("bulkPurchase", "amt", _amt);
const warehouse = getWarehouse(divisionName, cityName) const warehouse = getWarehouse(divisionName, cityName);
const material = getMaterial(divisionName, cityName, materialName); const material = getMaterial(divisionName, cityName, materialName);
BulkPurchase(corporation, warehouse, material, amt); BulkPurchase(corporation, warehouse, material, amt);
}, },
makeProduct: function ( makeProduct: function (
adivisionName: any, _divisionName: unknown,
acityName: any, _cityName: unknown,
aproductName: any, _productName: unknown,
adesignInvest: any, _designInvest: unknown,
amarketingInvest: any, _marketingInvest: unknown,
): void { ): void {
checkAccess("makeProduct", 7); checkAccess("makeProduct", 7);
const divisionName = helper.string("makeProduct", "divisionName", adivisionName); const divisionName = helper.string("makeProduct", "divisionName", _divisionName);
const cityName = helper.string("makeProduct", "cityName", acityName); const cityName = helper.city("makeProduct", "cityName", _cityName);
const productName = helper.string("makeProduct", "productName", aproductName); const productName = helper.string("makeProduct", "productName", _productName);
const designInvest = helper.number("makeProduct", "designInvest", adesignInvest); const designInvest = helper.number("makeProduct", "designInvest", _designInvest);
const marketingInvest = helper.number("makeProduct", "marketingInvest", amarketingInvest); const marketingInvest = helper.number("makeProduct", "marketingInvest", _marketingInvest);
const corporation = getCorporation(); const corporation = getCorporation();
MakeProduct(corporation, getDivision(divisionName), cityName, productName, designInvest, marketingInvest); MakeProduct(corporation, getDivision(divisionName), cityName, productName, designInvest, marketingInvest);
}, },
exportMaterial: function ( exportMaterial: function (
asourceDivision: any, _sourceDivision: unknown,
asourceCity: any, _sourceCity: unknown,
atargetDivision: any, _targetDivision: unknown,
atargetCity: any, _targetCity: unknown,
amaterialName: any, _materialName: unknown,
aamt: any, _amt: unknown,
): void { ): void {
checkAccess("exportMaterial", 7); checkAccess("exportMaterial", 7);
const sourceDivision = helper.string("exportMaterial", "sourceDivision", asourceDivision); const sourceDivision = helper.string("exportMaterial", "sourceDivision", _sourceDivision);
const sourceCity = helper.string("exportMaterial", "sourceCity", asourceCity); const sourceCity = helper.string("exportMaterial", "sourceCity", _sourceCity);
const targetDivision = helper.string("exportMaterial", "targetDivision", atargetDivision); const targetDivision = helper.string("exportMaterial", "targetDivision", _targetDivision);
const targetCity = helper.string("exportMaterial", "targetCity", atargetCity); const targetCity = helper.string("exportMaterial", "targetCity", _targetCity);
const materialName = helper.string("exportMaterial", "materialName", amaterialName); const materialName = helper.string("exportMaterial", "materialName", _materialName);
const amt = helper.string("exportMaterial", "amt", aamt); const amt = helper.string("exportMaterial", "amt", _amt);
ExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + "", getDivision(targetDivision)); ExportMaterial(
targetDivision,
targetCity,
getMaterial(sourceDivision, sourceCity, materialName),
amt + "",
getDivision(targetDivision),
);
}, },
cancelExportMaterial: function ( cancelExportMaterial: function (
asourceDivision: any, _sourceDivision: unknown,
asourceCity: any, _sourceCity: unknown,
atargetDivision: any, _targetDivision: unknown,
atargetCity: any, _targetCity: unknown,
amaterialName: any, _materialName: unknown,
aamt: any, _amt: unknown,
): void { ): void {
checkAccess("cancelExportMaterial", 7); checkAccess("cancelExportMaterial", 7);
const sourceDivision = helper.string("cancelExportMaterial", "sourceDivision", asourceDivision); const sourceDivision = helper.string("cancelExportMaterial", "sourceDivision", _sourceDivision);
const sourceCity = helper.string("cancelExportMaterial", "sourceCity", asourceCity); const sourceCity = helper.string("cancelExportMaterial", "sourceCity", _sourceCity);
const targetDivision = helper.string("cancelExportMaterial", "targetDivision", atargetDivision); const targetDivision = helper.string("cancelExportMaterial", "targetDivision", _targetDivision);
const targetCity = helper.string("cancelExportMaterial", "targetCity", atargetCity); const targetCity = helper.string("cancelExportMaterial", "targetCity", _targetCity);
const materialName = helper.string("cancelExportMaterial", "materialName", amaterialName); const materialName = helper.string("cancelExportMaterial", "materialName", _materialName);
const amt = helper.string("cancelExportMaterial", "amt", aamt); const amt = helper.string("cancelExportMaterial", "amt", _amt);
CancelExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + ""); CancelExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + "");
}, },
setMaterialMarketTA1: function (adivisionName: any, acityName: any, amaterialName: any, aon: any): void { setMaterialMarketTA1: function (
_divisionName: unknown,
_cityName: unknown,
_materialName: unknown,
_on: unknown,
): void {
checkAccess("setMaterialMarketTA1", 7); checkAccess("setMaterialMarketTA1", 7);
const divisionName = helper.string("setMaterialMarketTA1", "divisionName", adivisionName); const divisionName = helper.string("setMaterialMarketTA1", "divisionName", _divisionName);
const cityName = helper.string("setMaterialMarketTA1", "cityName", acityName); const cityName = helper.city("setMaterialMarketTA1", "cityName", _cityName);
const materialName = helper.string("setMaterialMarketTA1", "materialName", amaterialName); const materialName = helper.string("setMaterialMarketTA1", "materialName", _materialName);
const on = helper.boolean(aon); const on = helper.boolean(_on);
if (!getDivision(divisionName).hasResearch("Market-TA.I")) if (!getDivision(divisionName).hasResearch("Market-TA.I"))
throw helper.makeRuntimeErrorMsg(`corporation.setMaterialMarketTA1`, `You have not researched MarketTA.I for division: ${divisionName}`); throw helper.makeRuntimeErrorMsg(
`corporation.setMaterialMarketTA1`,
`You have not researched MarketTA.I for division: ${divisionName}`,
);
SetMaterialMarketTA1(getMaterial(divisionName, cityName, materialName), on); SetMaterialMarketTA1(getMaterial(divisionName, cityName, materialName), on);
}, },
setMaterialMarketTA2: function (adivisionName: any, acityName: any, amaterialName: any, aon: any): void { setMaterialMarketTA2: function (
_divisionName: unknown,
_cityName: unknown,
_materialName: unknown,
_on: unknown,
): void {
checkAccess("setMaterialMarketTA2", 7); checkAccess("setMaterialMarketTA2", 7);
const divisionName = helper.string("setMaterialMarketTA2", "divisionName", adivisionName); const divisionName = helper.string("setMaterialMarketTA2", "divisionName", _divisionName);
const cityName = helper.string("setMaterialMarketTA2", "cityName", acityName); const cityName = helper.city("setMaterialMarketTA2", "cityName", _cityName);
const materialName = helper.string("setMaterialMarketTA2", "materialName", amaterialName); const materialName = helper.string("setMaterialMarketTA2", "materialName", _materialName);
const on = helper.boolean(aon); const on = helper.boolean(_on);
if (!getDivision(divisionName).hasResearch("Market-TA.II")) if (!getDivision(divisionName).hasResearch("Market-TA.II"))
throw helper.makeRuntimeErrorMsg(`corporation.setMaterialMarketTA2`, `You have not researched MarketTA.II for division: ${divisionName}`); throw helper.makeRuntimeErrorMsg(
`corporation.setMaterialMarketTA2`,
`You have not researched MarketTA.II for division: ${divisionName}`,
);
SetMaterialMarketTA2(getMaterial(divisionName, cityName, materialName), on); SetMaterialMarketTA2(getMaterial(divisionName, cityName, materialName), on);
}, },
setProductMarketTA1: function (adivisionName: any, aproductName: any, aon: any): void { setProductMarketTA1: function (_divisionName: unknown, _productName: unknown, _on: unknown): void {
checkAccess("setProductMarketTA1", 7); checkAccess("setProductMarketTA1", 7);
const divisionName = helper.string("setProductMarketTA1", "divisionName", adivisionName); const divisionName = helper.string("setProductMarketTA1", "divisionName", _divisionName);
const productName = helper.string("setProductMarketTA1", "productName", aproductName); const productName = helper.string("setProductMarketTA1", "productName", _productName);
const on = helper.boolean(aon); const on = helper.boolean(_on);
if (!getDivision(divisionName).hasResearch("Market-TA.I")) if (!getDivision(divisionName).hasResearch("Market-TA.I"))
throw helper.makeRuntimeErrorMsg(`corporation.setProductMarketTA1`, `You have not researched MarketTA.I for division: ${divisionName}`); throw helper.makeRuntimeErrorMsg(
`corporation.setProductMarketTA1`,
`You have not researched MarketTA.I for division: ${divisionName}`,
);
SetProductMarketTA1(getProduct(divisionName, productName), on); SetProductMarketTA1(getProduct(divisionName, productName), on);
}, },
setProductMarketTA2: function (adivisionName: any, aproductName: any, aon: any): void { setProductMarketTA2: function (_divisionName: unknown, _productName: unknown, _on: unknown): void {
checkAccess("setProductMarketTA2", 7); checkAccess("setProductMarketTA2", 7);
const divisionName = helper.string("setProductMarketTA2", "divisionName", adivisionName); const divisionName = helper.string("setProductMarketTA2", "divisionName", _divisionName);
const productName = helper.string("setProductMarketTA2", "productName", aproductName); const productName = helper.string("setProductMarketTA2", "productName", _productName);
const on = helper.boolean(aon); const on = helper.boolean(_on);
if (!getDivision(divisionName).hasResearch("Market-TA.II")) if (!getDivision(divisionName).hasResearch("Market-TA.II"))
throw helper.makeRuntimeErrorMsg(`corporation.setProductMarketTA2`, `You have not researched MarketTA.II for division: ${divisionName}`); throw helper.makeRuntimeErrorMsg(
`corporation.setProductMarketTA2`,
`You have not researched MarketTA.II for division: ${divisionName}`,
);
SetProductMarketTA2(getProduct(divisionName, productName), on); SetProductMarketTA2(getProduct(divisionName, productName), on);
}, },
}; };
const officeAPI: OfficeAPI = { const officeAPI: OfficeAPI = {
getHireAdVertCost: function (adivisionName: any): number { getHireAdVertCost: function (_divisionName: unknown): number {
checkAccess("getHireAdVertCost", 8); checkAccess("getHireAdVertCost", 8);
const divisionName = helper.string("getHireAdVertCost", "divisionName", adivisionName); const divisionName = helper.string("getHireAdVertCost", "divisionName", _divisionName);
const division = getDivision(divisionName); const division = getDivision(divisionName);
const upgrade = IndustryUpgrades[1]; const upgrade = IndustryUpgrades[1];
return upgrade[1] * Math.pow(upgrade[2], division.upgrades[1]); return upgrade[1] * Math.pow(upgrade[2], division.upgrades[1]);
}, },
getHireAdVertCount: function (adivisionName: any): number { getHireAdVertCount: function (_divisionName: unknown): number {
checkAccess("getHireAdVertCount", 8); checkAccess("getHireAdVertCount", 8);
const divisionName = helper.string("getHireAdVertCount", "divisionName", adivisionName); const divisionName = helper.string("getHireAdVertCount", "divisionName", _divisionName);
const division = getDivision(divisionName); const division = getDivision(divisionName);
return division.upgrades[1] return division.upgrades[1];
}, },
getResearchCost: function (adivisionName: any, aresearchName: any): number { getResearchCost: function (_divisionName: unknown, _researchName: unknown): number {
checkAccess("getResearchCost", 8); checkAccess("getResearchCost", 8);
const divisionName = helper.string("getResearchCost", "divisionName", adivisionName); const divisionName = helper.string("getResearchCost", "divisionName", _divisionName);
const researchName = helper.string("getResearchCost", "researchName", aresearchName); const researchName = helper.string("getResearchCost", "researchName", _researchName);
return getResearchCost(getDivision(divisionName), researchName); return getResearchCost(getDivision(divisionName), researchName);
}, },
hasResearched: function (adivisionName: any, aresearchName: any): boolean { hasResearched: function (_divisionName: unknown, _researchName: unknown): boolean {
checkAccess("hasResearched", 8); checkAccess("hasResearched", 8);
const divisionName = helper.string("hasResearched", "divisionName", adivisionName); const divisionName = helper.string("hasResearched", "divisionName", _divisionName);
const researchName = helper.string("hasResearched", "researchName", aresearchName); const researchName = helper.string("hasResearched", "researchName", _researchName);
return hasResearched(getDivision(divisionName), researchName); return hasResearched(getDivision(divisionName), researchName);
}, },
setAutoJobAssignment: function (adivisionName: any, acityName: any, ajob: any, aamount: any): Promise<boolean> { setAutoJobAssignment: function (
_divisionName: unknown,
_cityName: unknown,
_job: unknown,
_amount: unknown,
): Promise<boolean> {
checkAccess("setAutoJobAssignment", 8); checkAccess("setAutoJobAssignment", 8);
const divisionName = helper.string("setAutoJobAssignment", "divisionName", adivisionName); const divisionName = helper.string("setAutoJobAssignment", "divisionName", _divisionName);
const cityName = helper.string("setAutoJobAssignment", "cityName", acityName); const cityName = helper.city("setAutoJobAssignment", "cityName", _cityName);
const amount = helper.number("setAutoJobAssignment", "amount", aamount); const amount = helper.number("setAutoJobAssignment", "amount", _amount);
const job = helper.string("setAutoJobAssignment", "job", ajob); const job = helper.string("setAutoJobAssignment", "job", _job);
const office = getOffice(divisionName, cityName); const office = getOffice(divisionName, cityName);
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`); if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
return netscriptDelay(1000, workerScript).then(function () { return netscriptDelay(1000, workerScript).then(function () {
@ -583,11 +643,11 @@ export function NetscriptCorporation(
return Promise.resolve(office.setEmployeeToJob(job, amount)); return Promise.resolve(office.setEmployeeToJob(job, amount));
}); });
}, },
getOfficeSizeUpgradeCost: function (adivisionName: any, acityName: any, asize: any): number { getOfficeSizeUpgradeCost: function (_divisionName: unknown, _cityName: unknown, _size: unknown): number {
checkAccess("getOfficeSizeUpgradeCost", 8); checkAccess("getOfficeSizeUpgradeCost", 8);
const divisionName = helper.string("getOfficeSizeUpgradeCost", "divisionName", adivisionName); const divisionName = helper.string("getOfficeSizeUpgradeCost", "divisionName", _divisionName);
const cityName = helper.string("getOfficeSizeUpgradeCost", "cityName", acityName); const cityName = helper.city("getOfficeSizeUpgradeCost", "cityName", _cityName);
const size = helper.number("getOfficeSizeUpgradeCost", "size", asize); const size = helper.number("getOfficeSizeUpgradeCost", "size", _size);
if (size < 0) throw new Error("Invalid value for size field! Must be numeric and greater than 0"); if (size < 0) throw new Error("Invalid value for size field! Must be numeric and greater than 0");
const office = getOffice(divisionName, cityName); const office = getOffice(divisionName, cityName);
const initialPriceMult = Math.round(office.size / CorporationConstants.OfficeInitialSize); const initialPriceMult = Math.round(office.size / CorporationConstants.OfficeInitialSize);
@ -598,40 +658,46 @@ export function NetscriptCorporation(
} }
return CorporationConstants.OfficeInitialCost * mult; return CorporationConstants.OfficeInitialCost * mult;
}, },
assignJob: function (adivisionName: any, acityName: any, aemployeeName: any, ajob: any): Promise<void> { assignJob: function (
_divisionName: unknown,
_cityName: unknown,
_employeeName: unknown,
_job: unknown,
): Promise<void> {
checkAccess("assignJob", 8); checkAccess("assignJob", 8);
const divisionName = helper.string("assignJob", "divisionName", adivisionName); const divisionName = helper.string("assignJob", "divisionName", _divisionName);
const cityName = helper.string("assignJob", "cityName", acityName); const cityName = helper.city("assignJob", "cityName", _cityName);
const employeeName = helper.string("assignJob", "employeeName", aemployeeName); const employeeName = helper.string("assignJob", "employeeName", _employeeName);
const job = helper.string("assignJob", "job", ajob); const job = helper.string("assignJob", "job", _job);
const employee = getEmployee(divisionName, cityName, employeeName); const employee = getEmployee(divisionName, cityName, employeeName);
return netscriptDelay(1000, workerScript).then(function () { return netscriptDelay(1000, workerScript).then(function () {
return Promise.resolve(AssignJob(employee, job)); return Promise.resolve(AssignJob(employee, job));
}); });
}, },
hireEmployee: function (adivisionName: any, acityName: any): any { hireEmployee: function (_divisionName: unknown, _cityName: unknown): any {
checkAccess("hireEmployee", 8); checkAccess("hireEmployee", 8);
const divisionName = helper.string("hireEmployee", "divisionName", adivisionName); const divisionName = helper.string("hireEmployee", "divisionName", _divisionName);
const cityName = helper.string("hireEmployee", "cityName", acityName); const cityName = helper.city("hireEmployee", "cityName", _cityName);
const office = getOffice(divisionName, cityName); const office = getOffice(divisionName, cityName);
return office.hireRandomEmployee(); return office.hireRandomEmployee();
}, },
upgradeOfficeSize: function (adivisionName: any, acityName: any, asize: any): void { upgradeOfficeSize: function (_divisionName: unknown, _cityName: unknown, _size: unknown): void {
checkAccess("upgradeOfficeSize", 8); checkAccess("upgradeOfficeSize", 8);
const divisionName = helper.string("upgradeOfficeSize", "divisionName", adivisionName); const divisionName = helper.string("upgradeOfficeSize", "divisionName", _divisionName);
const cityName = helper.string("upgradeOfficeSize", "cityName", acityName); const cityName = helper.city("upgradeOfficeSize", "cityName", _cityName);
const size = helper.number("upgradeOfficeSize", "size", asize); const size = helper.number("upgradeOfficeSize", "size", _size);
if (size < 0) throw new Error("Invalid value for size field! Must be numeric and greater than 0"); if (size < 0) throw new Error("Invalid value for size field! Must be numeric and greater than 0");
const office = getOffice(divisionName, cityName); const office = getOffice(divisionName, cityName);
const corporation = getCorporation(); const corporation = getCorporation();
UpgradeOfficeSize(corporation, office, size); UpgradeOfficeSize(corporation, office, size);
}, },
throwParty: function (adivisionName: any, acityName: any, acostPerEmployee: any): Promise<number> { throwParty: function (_divisionName: unknown, _cityName: unknown, _costPerEmployee: unknown): Promise<number> {
checkAccess("throwParty", 8); checkAccess("throwParty", 8);
const divisionName = helper.string("throwParty", "divisionName", adivisionName); const divisionName = helper.string("throwParty", "divisionName", _divisionName);
const cityName = helper.string("throwParty", "cityName", acityName); const cityName = helper.city("throwParty", "cityName", _cityName);
const costPerEmployee = helper.number("throwParty", "costPerEmployee", acostPerEmployee); const costPerEmployee = helper.number("throwParty", "costPerEmployee", _costPerEmployee);
if (costPerEmployee < 0) throw new Error("Invalid value for Cost Per Employee field! Must be numeric and greater than 0"); if (costPerEmployee < 0)
throw new Error("Invalid value for Cost Per Employee field! Must be numeric and greater than 0");
const office = getOffice(divisionName, cityName); const office = getOffice(divisionName, cityName);
const corporation = getCorporation(); const corporation = getCorporation();
return netscriptDelay( return netscriptDelay(
@ -641,10 +707,10 @@ export function NetscriptCorporation(
return Promise.resolve(ThrowParty(corporation, office, costPerEmployee)); return Promise.resolve(ThrowParty(corporation, office, costPerEmployee));
}); });
}, },
buyCoffee: function (adivisionName: any, acityName: any): Promise<void> { buyCoffee: function (_divisionName: unknown, _cityName: unknown): Promise<void> {
checkAccess("buyCoffee", 8); checkAccess("buyCoffee", 8);
const divisionName = helper.string("buyCoffee", "divisionName", adivisionName); const divisionName = helper.string("buyCoffee", "divisionName", _divisionName);
const cityName = helper.string("buyCoffee", "cityName", acityName); const cityName = helper.city("buyCoffee", "cityName", _cityName);
const corporation = getCorporation(); const corporation = getCorporation();
return netscriptDelay( return netscriptDelay(
(60 * 1000) / (player.hacking_speed_mult * calculateIntelligenceBonus(player.intelligence, 1)), (60 * 1000) / (player.hacking_speed_mult * calculateIntelligenceBonus(player.intelligence, 1)),
@ -653,22 +719,22 @@ export function NetscriptCorporation(
return Promise.resolve(BuyCoffee(corporation, getDivision(divisionName), getOffice(divisionName, cityName))); return Promise.resolve(BuyCoffee(corporation, getDivision(divisionName), getOffice(divisionName, cityName)));
}); });
}, },
hireAdVert: function (adivisionName: any): void { hireAdVert: function (_divisionName: unknown): void {
checkAccess("hireAdVert", 8); checkAccess("hireAdVert", 8);
const divisionName = helper.string("hireAdVert", "divisionName", adivisionName); const divisionName = helper.string("hireAdVert", "divisionName", _divisionName);
const corporation = getCorporation(); const corporation = getCorporation();
HireAdVert(corporation, getDivision(divisionName), getOffice(divisionName, "Sector-12")); HireAdVert(corporation, getDivision(divisionName), getOffice(divisionName, "Sector-12"));
}, },
research: function (adivisionName: any, aresearchName: any): void { research: function (_divisionName: unknown, _researchName: unknown): void {
checkAccess("research", 8); checkAccess("research", 8);
const divisionName = helper.string("research", "divisionName", adivisionName); const divisionName = helper.string("research", "divisionName", _divisionName);
const researchName = helper.string("research", "researchName", aresearchName); const researchName = helper.string("research", "researchName", _researchName);
Research(getDivision(divisionName), researchName); Research(getDivision(divisionName), researchName);
}, },
getOffice: function (adivisionName: any, acityName: any): any { getOffice: function (_divisionName: unknown, _cityName: unknown): any {
checkAccess("getOffice", 8); checkAccess("getOffice", 8);
const divisionName = helper.string("getOffice", "divisionName", adivisionName); const divisionName = helper.string("getOffice", "divisionName", _divisionName);
const cityName = helper.string("getOffice", "cityName", acityName); const cityName = helper.city("getOffice", "cityName", _cityName);
const office = getOffice(divisionName, cityName); const office = getOffice(divisionName, cityName);
return { return {
loc: office.loc, loc: office.loc,
@ -689,11 +755,11 @@ export function NetscriptCorporation(
}, },
}; };
}, },
getEmployee: function (adivisionName: any, acityName: any, aemployeeName: any): NSEmployee { getEmployee: function (_divisionName: unknown, _cityName: unknown, _employeeName: unknown): NSEmployee {
checkAccess("getEmployee", 8); checkAccess("getEmployee", 8);
const divisionName = helper.string("getEmployee", "divisionName", adivisionName); const divisionName = helper.string("getEmployee", "divisionName", _divisionName);
const cityName = helper.string("getEmployee", "cityName", acityName); const cityName = helper.city("getEmployee", "cityName", _cityName);
const employeeName = helper.string("getEmployee", "employeeName", aemployeeName); const employeeName = helper.string("getEmployee", "employeeName", _employeeName);
const employee = getEmployee(divisionName, cityName, employeeName); const employee = getEmployee(divisionName, cityName, employeeName);
return { return {
name: employee.name, name: employee.name,
@ -715,42 +781,43 @@ export function NetscriptCorporation(
return { return {
...warehouseAPI, ...warehouseAPI,
...officeAPI, ...officeAPI,
expandIndustry: function (aindustryName: any, adivisionName: any): void { expandIndustry: function (_industryName: unknown, _divisionName: unknown): void {
checkAccess("expandIndustry"); checkAccess("expandIndustry");
const industryName = helper.string("expandIndustry", "industryName", aindustryName); const industryName = helper.string("expandIndustry", "industryName", _industryName);
const divisionName = helper.string("expandIndustry", "divisionName", adivisionName); const divisionName = helper.string("expandIndustry", "divisionName", _divisionName);
const corporation = getCorporation(); const corporation = getCorporation();
NewIndustry(corporation, industryName, divisionName); NewIndustry(corporation, industryName, divisionName);
}, },
expandCity: function (adivisionName: any, acityName: any): void { expandCity: function (_divisionName: unknown, _cityName: unknown): void {
checkAccess("expandCity"); checkAccess("expandCity");
const divisionName = helper.string("expandCity", "divisionName", adivisionName); const divisionName = helper.string("expandCity", "divisionName", _divisionName);
const cityName = helper.string("expandCity", "cityName", acityName); const cityName = helper.city("expandCity", "cityName", _cityName);
if (!CorporationConstants.Cities.includes(cityName)) throw new Error("Invalid city name"); if (!CorporationConstants.Cities.includes(cityName)) throw new Error("Invalid city name");
const corporation = getCorporation(); const corporation = getCorporation();
const division = getDivision(divisionName); const division = getDivision(divisionName);
NewCity(corporation, division, cityName); NewCity(corporation, division, cityName);
}, },
unlockUpgrade: function (aupgradeName: any): void { unlockUpgrade: function (_upgradeName: unknown): void {
checkAccess("unlockUpgrade"); checkAccess("unlockUpgrade");
const upgradeName = helper.string("unlockUpgrade", "upgradeName", aupgradeName); const upgradeName = helper.string("unlockUpgrade", "upgradeName", _upgradeName);
const corporation = getCorporation(); const corporation = getCorporation();
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName); const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName);
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`); if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
UnlockUpgrade(corporation, upgrade); UnlockUpgrade(corporation, upgrade);
}, },
levelUpgrade: function (aupgradeName: any): void { levelUpgrade: function (_upgradeName: unknown): void {
checkAccess("levelUpgrade"); checkAccess("levelUpgrade");
const upgradeName = helper.string("levelUpgrade", "upgradeName", aupgradeName); const upgradeName = helper.string("levelUpgrade", "upgradeName", _upgradeName);
const corporation = getCorporation(); const corporation = getCorporation();
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName); const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`); if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
LevelUpgrade(corporation, upgrade); LevelUpgrade(corporation, upgrade);
}, },
issueDividends: function (apercent: any): void { issueDividends: function (_percent: unknown): void {
checkAccess("issueDividends"); checkAccess("issueDividends");
const percent = helper.number("issueDividends", "percent", apercent); const percent = helper.number("issueDividends", "percent", _percent);
if (percent < 0 || percent > 100) throw new Error("Invalid value for percent field! Must be numeric, greater than 0, and less than 100"); if (percent < 0 || percent > 100)
throw new Error("Invalid value for percent field! Must be numeric, greater than 0, and less than 100");
const corporation = getCorporation(); const corporation = getCorporation();
if (!corporation.public) if (!corporation.public)
throw helper.makeRuntimeErrorMsg(`corporation.issueDividends`, `Your company has not gone public!`); throw helper.makeRuntimeErrorMsg(`corporation.issueDividends`, `Your company has not gone public!`);
@ -759,9 +826,9 @@ export function NetscriptCorporation(
// If you modify these objects you will affect them for real, it's not // If you modify these objects you will affect them for real, it's not
// copies. // copies.
getDivision: function (adivisionName: any): NSDivision { getDivision: function (_divisionName: unknown): NSDivision {
checkAccess("getDivision"); checkAccess("getDivision");
const divisionName = helper.string("getDivision", "divisionName", adivisionName); const divisionName = helper.string("getDivision", "divisionName", _divisionName);
const division = getDivision(divisionName); const division = getDivision(divisionName);
return getSafeDivision(division); return getSafeDivision(division);
}, },
@ -783,33 +850,34 @@ export function NetscriptCorporation(
divisions: corporation.divisions.map((division): NSDivision => getSafeDivision(division)), divisions: corporation.divisions.map((division): NSDivision => getSafeDivision(division)),
}; };
}, },
createCorporation: function (acorporationName: string, selfFund = true): boolean { createCorporation: function (_corporationName: unknown, _selfFund: unknown = true): boolean {
const corporationName = helper.string("createCorporation", "corporationName", acorporationName); const corporationName = helper.string("createCorporation", "corporationName", _corporationName);
const selfFund = helper.boolean(_selfFund);
return createCorporation(corporationName, selfFund); return createCorporation(corporationName, selfFund);
}, },
hasUnlockUpgrade: function (aupgradeName: any): boolean { hasUnlockUpgrade: function (_upgradeName: unknown): boolean {
checkAccess("hasUnlockUpgrade"); checkAccess("hasUnlockUpgrade");
const upgradeName = helper.string("hasUnlockUpgrade", "upgradeName", aupgradeName); const upgradeName = helper.string("hasUnlockUpgrade", "upgradeName", _upgradeName);
return hasUnlockUpgrade(upgradeName); return hasUnlockUpgrade(upgradeName);
}, },
getUnlockUpgradeCost: function (aupgradeName: any): number { getUnlockUpgradeCost: function (_upgradeName: unknown): number {
checkAccess("getUnlockUpgradeCost"); checkAccess("getUnlockUpgradeCost");
const upgradeName = helper.string("getUnlockUpgradeCost", "upgradeName", aupgradeName); const upgradeName = helper.string("getUnlockUpgradeCost", "upgradeName", _upgradeName);
return getUnlockUpgradeCost(upgradeName); return getUnlockUpgradeCost(upgradeName);
}, },
getUpgradeLevel: function (aupgradeName: any): number { getUpgradeLevel: function (_upgradeName: unknown): number {
checkAccess("hasUnlockUpgrade"); checkAccess("hasUnlockUpgrade");
const upgradeName = helper.string("getUpgradeLevel", "upgradeName", aupgradeName); const upgradeName = helper.string("getUpgradeLevel", "upgradeName", _upgradeName);
return getUpgradeLevel(upgradeName); return getUpgradeLevel(upgradeName);
}, },
getUpgradeLevelCost: function (aupgradeName: any): number { getUpgradeLevelCost: function (_upgradeName: unknown): number {
checkAccess("getUpgradeLevelCost"); checkAccess("getUpgradeLevelCost");
const upgradeName = helper.string("getUpgradeLevelCost", "upgradeName", aupgradeName); const upgradeName = helper.string("getUpgradeLevelCost", "upgradeName", _upgradeName);
return getUpgradeLevelCost(upgradeName); return getUpgradeLevelCost(upgradeName);
}, },
getExpandIndustryCost: function (aindustryName: any): number { getExpandIndustryCost: function (_industryName: unknown): number {
checkAccess("getExpandIndustryCost"); checkAccess("getExpandIndustryCost");
const industryName = helper.string("getExpandIndustryCost", "industryName", aindustryName); const industryName = helper.string("getExpandIndustryCost", "industryName", _industryName);
return getExpandIndustryCost(industryName); return getExpandIndustryCost(industryName);
}, },
getExpandCityCost: function (): number { getExpandCityCost: function (): number {
@ -824,31 +892,31 @@ export function NetscriptCorporation(
checkAccess("acceptInvestmentOffer"); checkAccess("acceptInvestmentOffer");
return acceptInvestmentOffer(); return acceptInvestmentOffer();
}, },
goPublic: function (anumShares: any): boolean { goPublic: function (_numShares: unknown): boolean {
checkAccess("acceptInvestmentOffer"); checkAccess("acceptInvestmentOffer");
const numShares = helper.number("goPublic", "numShares", anumShares); const numShares = helper.number("goPublic", "numShares", _numShares);
return goPublic(numShares); return goPublic(numShares);
}, },
sellShares: function (anumShares: any): number { sellShares: function (_numShares: unknown): number {
checkAccess("acceptInvestmentOffer"); checkAccess("acceptInvestmentOffer");
const numShares = helper.number("sellStock", "numShares", anumShares); const numShares = helper.number("sellStock", "numShares", _numShares);
return SellShares(getCorporation(), player, numShares); return SellShares(getCorporation(), player, numShares);
}, },
buyBackShares: function (anumShares: any): boolean { buyBackShares: function (_numShares: unknown): boolean {
checkAccess("acceptInvestmentOffer"); checkAccess("acceptInvestmentOffer");
const numShares = helper.number("buyStock", "numShares", anumShares); const numShares = helper.number("buyStock", "numShares", _numShares);
return BuyBackShares(getCorporation(), player, numShares); return BuyBackShares(getCorporation(), player, numShares);
}, },
bribe: function (afactionName: string, aamountCash: any, aamountShares: any): boolean { bribe: function (_factionName: unknown, _amountCash: unknown, _amountShares: unknown): boolean {
checkAccess("bribe"); checkAccess("bribe");
const factionName = helper.string("bribe", "factionName", afactionName); const factionName = helper.string("bribe", "factionName", _factionName);
const amountCash = helper.number("bribe", "amountCash", aamountCash); const amountCash = helper.number("bribe", "amountCash", _amountCash);
const amountShares = helper.number("bribe", "amountShares", aamountShares); const amountShares = helper.number("bribe", "amountShares", _amountShares);
return bribe(factionName, amountCash, amountShares); return bribe(factionName, amountCash, amountShares);
}, },
getBonusTime: function (): number { getBonusTime: function (): number {
checkAccess("getBonusTime"); checkAccess("getBonusTime");
return Math.round(getCorporation().storedCycles / 5) * 1000; return Math.round(getCorporation().storedCycles / 5) * 1000;
} },
}; };
} }

@ -1,5 +1,5 @@
import { FactionNames } from '../Faction/data/FactionNames'; import { FactionNames } from "../Faction/data/FactionNames";
import { GangConstants } from '../Gang/data/Constants'; import { GangConstants } from "../Gang/data/Constants";
import { INetscriptHelper } from "./INetscriptHelper"; import { INetscriptHelper } from "./INetscriptHelper";
import { IPlayer } from "../PersonObjects/IPlayer"; import { IPlayer } from "../PersonObjects/IPlayer";
import { getRamCost } from "../Netscript/RamCostGenerator"; import { getRamCost } from "../Netscript/RamCostGenerator";
@ -48,7 +48,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
}; };
return { return {
createGang: function (faction: string): boolean { createGang: function (_faction: unknown): boolean {
const faction = helper.string("createGang", "faction", _faction);
helper.updateDynamicRam("createGang", getRamCost(player, "gang", "createGang")); helper.updateDynamicRam("createGang", getRamCost(player, "gang", "createGang"));
// this list is copied from Faction/ui/Root.tsx // this list is copied from Faction/ui/Root.tsx
@ -101,12 +102,13 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return cpy; return cpy;
}, },
getMemberInformation: function (name: any): GangMemberInfo { getMemberInformation: function (_memberName: unknown): GangMemberInfo {
const memberName = helper.string("getMemberInformation", "memberName", _memberName);
helper.updateDynamicRam("getMemberInformation", getRamCost(player, "gang", "getMemberInformation")); helper.updateDynamicRam("getMemberInformation", getRamCost(player, "gang", "getMemberInformation"));
checkGangApiAccess("getMemberInformation"); checkGangApiAccess("getMemberInformation");
const gang = player.gang; const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang"); if (gang === null) throw new Error("Should not be called without Gang");
const member = getGangMember("getMemberInformation", name); const member = getGangMember("getMemberInformation", memberName);
return { return {
name: member.name, name: member.name,
task: member.task, task: member.task,
@ -161,16 +163,17 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
if (gang === null) throw new Error("Should not be called without Gang"); if (gang === null) throw new Error("Should not be called without Gang");
return gang.canRecruitMember(); return gang.canRecruitMember();
}, },
recruitMember: function (name: any): boolean { recruitMember: function (_memberName: unknown): boolean {
const memberName = helper.string("recruitMember", "memberName", _memberName);
helper.updateDynamicRam("recruitMember", getRamCost(player, "gang", "recruitMember")); helper.updateDynamicRam("recruitMember", getRamCost(player, "gang", "recruitMember"));
checkGangApiAccess("recruitMember"); checkGangApiAccess("recruitMember");
const gang = player.gang; const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang"); if (gang === null) throw new Error("Should not be called without Gang");
const recruited = gang.recruitMember(name); const recruited = gang.recruitMember(memberName);
if (recruited) { if (recruited) {
workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${name}'`); workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${memberName}'`);
} else { } else {
workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member '${name}'`); workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member '${memberName}'`);
} }
return recruited; return recruited;
@ -184,7 +187,9 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
tasks.unshift("Unassigned"); tasks.unshift("Unassigned");
return tasks; return tasks;
}, },
setMemberTask: function (memberName: any, taskName: any): boolean { setMemberTask: function (_memberName: unknown, _taskName: unknown): boolean {
const memberName = helper.string("setMemberTask", "memberName", _memberName);
const taskName = helper.string("setMemberTask", "taskName", _taskName);
helper.updateDynamicRam("setMemberTask", getRamCost(player, "gang", "setMemberTask")); helper.updateDynamicRam("setMemberTask", getRamCost(player, "gang", "setMemberTask"));
checkGangApiAccess("setMemberTask"); checkGangApiAccess("setMemberTask");
const member = getGangMember("setMemberTask", memberName); const member = getGangMember("setMemberTask", memberName);
@ -193,9 +198,10 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
if (!gang.getAllTaskNames().includes(taskName)) { if (!gang.getAllTaskNames().includes(taskName)) {
workerScript.log( workerScript.log(
"gang.setMemberTask", "gang.setMemberTask",
() => `Failed to assign Gang Member '${memberName}' to Invalid task '${taskName}'. '${memberName}' is now Unassigned`, () =>
`Failed to assign Gang Member '${memberName}' to Invalid task '${taskName}'. '${memberName}' is now Unassigned`,
); );
return member.assignToTask('Unassigned'); return member.assignToTask("Unassigned");
} }
const success = member.assignToTask(taskName); const success = member.assignToTask(taskName);
if (success) { if (success) {
@ -212,7 +218,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return success; return success;
}, },
getTaskStats: function (taskName: any): GangTaskStats { getTaskStats: function (_taskName: unknown): GangTaskStats {
const taskName = helper.string("getTaskStats", "taskName", _taskName);
helper.updateDynamicRam("getTaskStats", getRamCost(player, "gang", "getTaskStats")); helper.updateDynamicRam("getTaskStats", getRamCost(player, "gang", "getTaskStats"));
checkGangApiAccess("getTaskStats"); checkGangApiAccess("getTaskStats");
const task = getGangTask("getTaskStats", taskName); const task = getGangTask("getTaskStats", taskName);
@ -225,7 +232,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
checkGangApiAccess("getEquipmentNames"); checkGangApiAccess("getEquipmentNames");
return Object.keys(GangMemberUpgrades); return Object.keys(GangMemberUpgrades);
}, },
getEquipmentCost: function (equipName: any): number { getEquipmentCost: function (_equipName: any): number {
const equipName = helper.string("getEquipmentCost", "equipName", _equipName);
helper.updateDynamicRam("getEquipmentCost", getRamCost(player, "gang", "getEquipmentCost")); helper.updateDynamicRam("getEquipmentCost", getRamCost(player, "gang", "getEquipmentCost"));
checkGangApiAccess("getEquipmentCost"); checkGangApiAccess("getEquipmentCost");
const gang = player.gang; const gang = player.gang;
@ -234,14 +242,16 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
if (upg === null) return Infinity; if (upg === null) return Infinity;
return gang.getUpgradeCost(upg); return gang.getUpgradeCost(upg);
}, },
getEquipmentType: function (equipName: any): string { getEquipmentType: function (_equipName: unknown): string {
const equipName = helper.string("getEquipmentType", "equipName", _equipName);
helper.updateDynamicRam("getEquipmentType", getRamCost(player, "gang", "getEquipmentType")); helper.updateDynamicRam("getEquipmentType", getRamCost(player, "gang", "getEquipmentType"));
checkGangApiAccess("getEquipmentType"); checkGangApiAccess("getEquipmentType");
const upg = GangMemberUpgrades[equipName]; const upg = GangMemberUpgrades[equipName];
if (upg == null) return ""; if (upg == null) return "";
return upg.getType(); return upg.getType();
}, },
getEquipmentStats: function (equipName: any): EquipmentStats { getEquipmentStats: function (_equipName: unknown): EquipmentStats {
const equipName = helper.string("getEquipmentStats", "equipName", _equipName);
helper.updateDynamicRam("getEquipmentStats", getRamCost(player, "gang", "getEquipmentStats")); helper.updateDynamicRam("getEquipmentStats", getRamCost(player, "gang", "getEquipmentStats"));
checkGangApiAccess("getEquipmentStats"); checkGangApiAccess("getEquipmentStats");
const equipment = GangMemberUpgrades[equipName]; const equipment = GangMemberUpgrades[equipName];
@ -251,7 +261,9 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
const typecheck: EquipmentStats = equipment.mults; const typecheck: EquipmentStats = equipment.mults;
return Object.assign({}, typecheck) as any; return Object.assign({}, typecheck) as any;
}, },
purchaseEquipment: function (memberName: any, equipName: any): boolean { purchaseEquipment: function (_memberName: unknown, _equipName: unknown): boolean {
const memberName = helper.string("purchaseEquipment", "memberName", _memberName);
const equipName = helper.string("purchaseEquipment", "equipName", _equipName);
helper.updateDynamicRam("purchaseEquipment", getRamCost(player, "gang", "purchaseEquipment")); helper.updateDynamicRam("purchaseEquipment", getRamCost(player, "gang", "purchaseEquipment"));
checkGangApiAccess("purchaseEquipment"); checkGangApiAccess("purchaseEquipment");
const gang = player.gang; const gang = player.gang;
@ -271,28 +283,31 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
return res; return res;
}, },
ascendMember: function (name: any): GangMemberAscension | undefined { ascendMember: function (_memberName: unknown): GangMemberAscension | undefined {
const memberName = helper.string("ascendMember", "memberName", _memberName);
helper.updateDynamicRam("ascendMember", getRamCost(player, "gang", "ascendMember")); helper.updateDynamicRam("ascendMember", getRamCost(player, "gang", "ascendMember"));
checkGangApiAccess("ascendMember"); checkGangApiAccess("ascendMember");
const gang = player.gang; const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang"); if (gang === null) throw new Error("Should not be called without Gang");
const member = getGangMember("ascendMember", name); const member = getGangMember("ascendMember", memberName);
if (!member.canAscend()) return; if (!member.canAscend()) return;
return gang.ascendMember(member, workerScript); return gang.ascendMember(member, workerScript);
}, },
getAscensionResult: function (name: any): GangMemberAscension | undefined { getAscensionResult: function (_memberName: unknown): GangMemberAscension | undefined {
const memberName = helper.string("getAscensionResult", "memberName", _memberName);
helper.updateDynamicRam("getAscensionResult", getRamCost(player, "gang", "getAscensionResult")); helper.updateDynamicRam("getAscensionResult", getRamCost(player, "gang", "getAscensionResult"));
checkGangApiAccess("getAscensionResult"); checkGangApiAccess("getAscensionResult");
const gang = player.gang; const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang"); if (gang === null) throw new Error("Should not be called without Gang");
const member = getGangMember("getAscensionResult", name); const member = getGangMember("getAscensionResult", memberName);
if (!member.canAscend()) return; if (!member.canAscend()) return;
return { return {
respect: member.earnedRespect, respect: member.earnedRespect,
...member.getAscensionResults(), ...member.getAscensionResults(),
}; };
}, },
setTerritoryWarfare: function (engage: any): void { setTerritoryWarfare: function (_engage: unknown): void {
const engage = helper.boolean(_engage);
helper.updateDynamicRam("setTerritoryWarfare", getRamCost(player, "gang", "setTerritoryWarfare")); helper.updateDynamicRam("setTerritoryWarfare", getRamCost(player, "gang", "setTerritoryWarfare"));
checkGangApiAccess("setTerritoryWarfare"); checkGangApiAccess("setTerritoryWarfare");
const gang = player.gang; const gang = player.gang;
@ -305,7 +320,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
workerScript.log("gang.setTerritoryWarfare", () => "Disengaging in Gang Territory Warfare"); workerScript.log("gang.setTerritoryWarfare", () => "Disengaging in Gang Territory Warfare");
} }
}, },
getChanceToWinClash: function (otherGang: any): number { getChanceToWinClash: function (_otherGang: unknown): number {
const otherGang = helper.string("getChanceToWinClash", "otherGang", _otherGang);
helper.updateDynamicRam("getChanceToWinClash", getRamCost(player, "gang", "getChanceToWinClash")); helper.updateDynamicRam("getChanceToWinClash", getRamCost(player, "gang", "getChanceToWinClash"));
checkGangApiAccess("getChanceToWinClash"); checkGangApiAccess("getChanceToWinClash");
const gang = player.gang; const gang = player.gang;

@ -1,3 +1,4 @@
import { CityName } from "src/Locations/data/CityNames";
import { BaseServer } from "../Server/BaseServer"; import { BaseServer } from "../Server/BaseServer";
export interface INetscriptHelper { export interface INetscriptHelper {
@ -5,6 +6,7 @@ export interface INetscriptHelper {
makeRuntimeErrorMsg(functionName: string, message: string): void; makeRuntimeErrorMsg(functionName: string, message: string): void;
string(funcName: string, argName: string, v: unknown): string; string(funcName: string, argName: string, v: unknown): string;
number(funcName: string, argName: string, v: unknown): number; number(funcName: string, argName: string, v: unknown): number;
city(funcName: string, argName: string, v: unknown): CityName;
boolean(v: unknown): boolean; boolean(v: unknown): boolean;
getServer(ip: any, fn: any): BaseServer; getServer(ip: any, fn: any): BaseServer;
checkSingularityAccess(func: string): void; checkSingularityAccess(func: string): void;

@ -1,7 +1,7 @@
import { INetscriptHelper } from "./INetscriptHelper"; import { INetscriptHelper } from "./INetscriptHelper";
import { WorkerScript } from "../Netscript/WorkerScript"; import { WorkerScript } from "../Netscript/WorkerScript";
import { IPlayer } from "../PersonObjects/IPlayer"; import { IPlayer } from "../PersonObjects/IPlayer";
import { purchaseAugmentation, joinFaction } from "../Faction/FactionHelpers"; import { purchaseAugmentation, joinFaction, getFactionAugmentationsFiltered } from "../Faction/FactionHelpers";
import { startWorkerScript } from "../NetscriptWorker"; import { startWorkerScript } from "../NetscriptWorker";
import { Augmentation } from "../Augmentation/Augmentation"; import { Augmentation } from "../Augmentation/Augmentation";
import { Augmentations } from "../Augmentation/Augmentations"; import { Augmentations } from "../Augmentation/Augmentations";
@ -14,7 +14,13 @@ import { isString } from "../utils/helpers/isString";
import { getRamCost } from "../Netscript/RamCostGenerator"; import { getRamCost } from "../Netscript/RamCostGenerator";
import { RunningScript } from "../Script/RunningScript"; import { RunningScript } from "../Script/RunningScript";
import { Singularity as ISingularity } from "../ScriptEditor/NetscriptDefinitions"; import {
AugmentationStats,
CharacterInfo,
CrimeStats,
PlayerSkills,
Singularity as ISingularity,
} from "../ScriptEditor/NetscriptDefinitions";
import { findCrime } from "../Crime/CrimeHelpers"; import { findCrime } from "../Crime/CrimeHelpers";
import { CompanyPosition } from "../Company/CompanyPosition"; import { CompanyPosition } from "../Company/CompanyPosition";
@ -49,7 +55,7 @@ export function NetscriptSingularity(
workerScript: WorkerScript, workerScript: WorkerScript,
helper: INetscriptHelper, helper: INetscriptHelper,
): ISingularity { ): ISingularity {
const getAugmentation = function (func: any, name: any): Augmentation { const getAugmentation = function (func: string, name: string): Augmentation {
if (!augmentationExists(name)) { if (!augmentationExists(name)) {
throw helper.makeRuntimeErrorMsg(func, `Invalid augmentation: '${name}'`); throw helper.makeRuntimeErrorMsg(func, `Invalid augmentation: '${name}'`);
} }
@ -57,7 +63,7 @@ export function NetscriptSingularity(
return Augmentations[name]; return Augmentations[name];
}; };
const getFaction = function (func: any, name: any): Faction { const getFaction = function (func: string, name: string): Faction {
if (!factionExists(name)) { if (!factionExists(name)) {
throw helper.makeRuntimeErrorMsg(func, `Invalid faction name: '${name}`); throw helper.makeRuntimeErrorMsg(func, `Invalid faction name: '${name}`);
} }
@ -65,7 +71,7 @@ export function NetscriptSingularity(
return Factions[name]; return Factions[name];
}; };
const getCompany = function (func: any, name: any): Company { const getCompany = function (func: string, name: string): Company {
const company = Companies[name]; const company = Companies[name];
if (company == null || !(company instanceof Company)) { if (company == null || !(company instanceof Company)) {
throw helper.makeRuntimeErrorMsg(func, `Invalid company name: '${name}'`); throw helper.makeRuntimeErrorMsg(func, `Invalid company name: '${name}'`);
@ -73,26 +79,26 @@ export function NetscriptSingularity(
return company; return company;
}; };
const runAfterReset = function (cbScript = null): void { const runAfterReset = function (cbScript: string | null = null): void {
//Run a script after reset //Run a script after reset
if (cbScript && isString(cbScript)) { if (!cbScript) return;
const home = player.getHomeComputer(); const home = player.getHomeComputer();
for (const script of home.scripts) { for (const script of home.scripts) {
if (script.filename === cbScript) { if (script.filename === cbScript) {
const ramUsage = script.ramUsage; const ramUsage = script.ramUsage;
const ramAvailable = home.maxRam - home.ramUsed; const ramAvailable = home.maxRam - home.ramUsed;
if (ramUsage > ramAvailable) { if (ramUsage > ramAvailable) {
return; // Not enough RAM return; // Not enough RAM
}
const runningScriptObj = new RunningScript(script, []); // No args
runningScriptObj.threads = 1; // Only 1 thread
startWorkerScript(player, runningScriptObj, home);
} }
const runningScriptObj = new RunningScript(script, []); // No args
runningScriptObj.threads = 1; // Only 1 thread
startWorkerScript(player, runningScriptObj, home);
} }
} }
}; };
return { return {
getOwnedAugmentations: function (purchased: any = false): any { getOwnedAugmentations: function (_purchased: unknown = false): string[] {
const purchased = helper.boolean(_purchased);
helper.updateDynamicRam("getOwnedAugmentations", getRamCost(player, "getOwnedAugmentations")); helper.updateDynamicRam("getOwnedAugmentations", getRamCost(player, "getOwnedAugmentations"));
helper.checkSingularityAccess("getOwnedAugmentations"); helper.checkSingularityAccess("getOwnedAugmentations");
const res = []; const res = [];
@ -106,91 +112,63 @@ export function NetscriptSingularity(
} }
return res; return res;
}, },
getAugmentationsFromFaction: function (facname: any): any { getAugmentationsFromFaction: function (_facName: unknown): string[] {
const facName = helper.string("getAugmentationsFromFaction", "facName", _facName);
helper.updateDynamicRam("getAugmentationsFromFaction", getRamCost(player, "getAugmentationsFromFaction")); helper.updateDynamicRam("getAugmentationsFromFaction", getRamCost(player, "getAugmentationsFromFaction"));
helper.checkSingularityAccess("getAugmentationsFromFaction"); helper.checkSingularityAccess("getAugmentationsFromFaction");
const faction = getFaction("getAugmentationsFromFaction", facname); const faction = getFaction("getAugmentationsFromFaction", facName);
// If player has a gang with this faction, return all augmentations. return getFactionAugmentationsFiltered(player, faction);
if (player.hasGangWith(facname)) {
let augs = Object.values(Augmentations);
// Remove blacklisted augs.
const blacklist = [AugmentationNames.NeuroFluxGovernor, AugmentationNames.TheRedPill];
augs = augs.filter((a) => !blacklist.includes(a.name));
// Remove special augs.
augs = augs.filter((a) => !a.isSpecial);
// Remove faction-unique augs outside BN2. (But keep the one for this faction.)
if (player.bitNodeN !== 2) {
augs = augs.filter((a) => a.factions.length > 1 || Factions[facname].augmentations.includes(a.name));
}
return augs.map((a) => a.name);
}
return faction.augmentations.slice();
}, },
getAugmentationCost: function (name: any): any { getAugmentationCost: function (_augName: unknown): [number, number] {
const augName = helper.string("getAugmentationCost", "augName", _augName);
helper.updateDynamicRam("getAugmentationCost", getRamCost(player, "getAugmentationCost")); helper.updateDynamicRam("getAugmentationCost", getRamCost(player, "getAugmentationCost"));
helper.checkSingularityAccess("getAugmentationCost"); helper.checkSingularityAccess("getAugmentationCost");
const aug = getAugmentation("getAugmentationCost", name); const aug = getAugmentation("getAugmentationCost", augName);
return [aug.baseRepRequirement, aug.baseCost]; return [aug.baseRepRequirement, aug.baseCost];
}, },
getAugmentationPrereq: function (name: any): any { getAugmentationPrereq: function (_augName: unknown): string[] {
const augName = helper.string("getAugmentationPrereq", "augName", _augName);
helper.updateDynamicRam("getAugmentationPrereq", getRamCost(player, "getAugmentationPrereq")); helper.updateDynamicRam("getAugmentationPrereq", getRamCost(player, "getAugmentationPrereq"));
helper.checkSingularityAccess("getAugmentationPrereq"); helper.checkSingularityAccess("getAugmentationPrereq");
const aug = getAugmentation("getAugmentationPrereq", name); const aug = getAugmentation("getAugmentationPrereq", augName);
return aug.prereqs.slice(); return aug.prereqs.slice();
}, },
getAugmentationPrice: function (name: any): any { getAugmentationPrice: function (_augName: unknown): number {
const augName = helper.string("getAugmentationPrice", "augName", _augName);
helper.updateDynamicRam("getAugmentationPrice", getRamCost(player, "getAugmentationPrice")); helper.updateDynamicRam("getAugmentationPrice", getRamCost(player, "getAugmentationPrice"));
helper.checkSingularityAccess("getAugmentationPrice"); helper.checkSingularityAccess("getAugmentationPrice");
const aug = getAugmentation("getAugmentationPrice", name); const aug = getAugmentation("getAugmentationPrice", augName);
return aug.baseCost; return aug.baseCost;
}, },
getAugmentationRepReq: function (name: any): any { getAugmentationRepReq: function (_augName: unknown): number {
const augName = helper.string("getAugmentationRepReq", "augName", _augName);
helper.updateDynamicRam("getAugmentationRepReq", getRamCost(player, "getAugmentationRepReq")); helper.updateDynamicRam("getAugmentationRepReq", getRamCost(player, "getAugmentationRepReq"));
helper.checkSingularityAccess("getAugmentationRepReq"); helper.checkSingularityAccess("getAugmentationRepReq");
const aug = getAugmentation("getAugmentationRepReq", name); const aug = getAugmentation("getAugmentationRepReq", augName);
return aug.baseRepRequirement; return aug.baseRepRequirement;
}, },
getAugmentationStats: function (name: any): any { getAugmentationStats: function (_augName: unknown): AugmentationStats {
const augName = helper.string("getAugmentationStats", "augName", _augName);
helper.updateDynamicRam("getAugmentationStats", getRamCost(player, "getAugmentationStats")); helper.updateDynamicRam("getAugmentationStats", getRamCost(player, "getAugmentationStats"));
helper.checkSingularityAccess("getAugmentationStats"); helper.checkSingularityAccess("getAugmentationStats");
const aug = getAugmentation("getAugmentationStats", name); const aug = getAugmentation("getAugmentationStats", augName);
return Object.assign({}, aug.mults); return Object.assign({}, aug.mults);
}, },
purchaseAugmentation: function (faction: any, name: any): any { purchaseAugmentation: function (_facName: unknown, _augName: unknown): boolean {
const facName = helper.string("purchaseAugmentation", "facName", _facName);
const augName = helper.string("purchaseAugmentation", "augName", _augName);
helper.updateDynamicRam("purchaseAugmentation", getRamCost(player, "purchaseAugmentation")); helper.updateDynamicRam("purchaseAugmentation", getRamCost(player, "purchaseAugmentation"));
helper.checkSingularityAccess("purchaseAugmentation"); helper.checkSingularityAccess("purchaseAugmentation");
const fac = getFaction("purchaseAugmentation", faction); const fac = getFaction("purchaseAugmentation", facName);
const aug = getAugmentation("purchaseAugmentation", name); const aug = getAugmentation("purchaseAugmentation", augName);
let augs = []; const augs = getFactionAugmentationsFiltered(player, fac);
if (player.hasGangWith(faction)) {
for (const augName of Object.keys(Augmentations)) {
const aug = Augmentations[augName];
if (
augName === AugmentationNames.NeuroFluxGovernor ||
(augName === AugmentationNames.TheRedPill && player.bitNodeN !== 2) ||
// Special augs (i.e. Bladeburner augs)
aug.isSpecial ||
// Exclusive augs (i.e. QLink)
(aug.factions.length <= 1 && !fac.augmentations.includes(augName) && player.bitNodeN !== 2)
)
continue;
augs.push(augName);
}
} else {
augs = fac.augmentations;
}
if (!augs.includes(name)) { if (!augs.includes(augName)) {
workerScript.log( workerScript.log(
"purchaseAugmentation", "purchaseAugmentation",
() => `Faction '${faction}' does not have the '${name}' augmentation.`, () => `Faction '${facName}' does not have the '${augName}' augmentation.`,
); );
return false; return false;
} }
@ -199,13 +177,13 @@ export function NetscriptSingularity(
if (!isNeuroflux) { if (!isNeuroflux) {
for (let j = 0; j < player.queuedAugmentations.length; ++j) { for (let j = 0; j < player.queuedAugmentations.length; ++j) {
if (player.queuedAugmentations[j].name === aug.name) { if (player.queuedAugmentations[j].name === aug.name) {
workerScript.log("purchaseAugmentation", () => `You already have the '${name}' augmentation.`); workerScript.log("purchaseAugmentation", () => `You already have the '${augName}' augmentation.`);
return false; return false;
} }
} }
for (let j = 0; j < player.augmentations.length; ++j) { for (let j = 0; j < player.augmentations.length; ++j) {
if (player.augmentations[j].name === aug.name) { if (player.augmentations[j].name === aug.name) {
workerScript.log("purchaseAugmentation", () => `You already have the '${name}' augmentation.`); workerScript.log("purchaseAugmentation", () => `You already have the '${augName}' augmentation.`);
return false; return false;
} }
} }
@ -225,7 +203,8 @@ export function NetscriptSingularity(
return false; return false;
} }
}, },
softReset: function (cbScript: any): any { softReset: function (_cbScript: unknown): void {
const cbScript = helper.string("softReset", "cbScript", _cbScript);
helper.updateDynamicRam("softReset", getRamCost(player, "softReset")); helper.updateDynamicRam("softReset", getRamCost(player, "softReset"));
helper.checkSingularityAccess("softReset"); helper.checkSingularityAccess("softReset");
@ -239,7 +218,8 @@ export function NetscriptSingularity(
workerScript.running = false; workerScript.running = false;
killWorkerScript(workerScript); killWorkerScript(workerScript);
}, },
installAugmentations: function (cbScript: any): any { installAugmentations: function (_cbScript: unknown): boolean {
const cbScript = helper.string("installAugmentations", "cbScript", _cbScript);
helper.updateDynamicRam("installAugmentations", getRamCost(player, "installAugmentations")); helper.updateDynamicRam("installAugmentations", getRamCost(player, "installAugmentations"));
helper.checkSingularityAccess("installAugmentations"); helper.checkSingularityAccess("installAugmentations");
@ -259,9 +239,11 @@ export function NetscriptSingularity(
workerScript.running = false; // Prevent workerScript from "finishing execution naturally" workerScript.running = false; // Prevent workerScript from "finishing execution naturally"
killWorkerScript(workerScript); killWorkerScript(workerScript);
return true;
}, },
goToLocation: function (locationName: any): boolean { goToLocation: function (_locationName: unknown): boolean {
const locationName = helper.string("goToLocation", "locationName", _locationName);
helper.updateDynamicRam("goToLocation", getRamCost(player, "goToLocation")); helper.updateDynamicRam("goToLocation", getRamCost(player, "goToLocation"));
helper.checkSingularityAccess("goToLocation"); helper.checkSingularityAccess("goToLocation");
const location = Object.values(Locations).find((l) => l.name === locationName); const location = Object.values(Locations).find((l) => l.name === locationName);
@ -277,7 +259,10 @@ export function NetscriptSingularity(
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000);
return true; return true;
}, },
universityCourse: function (universityName: any, className: any, focus = true): any { universityCourse: function (_universityName: unknown, _className: unknown, _focus: unknown = true): boolean {
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.updateDynamicRam("universityCourse", getRamCost(player, "universityCourse"));
helper.checkSingularityAccess("universityCourse"); helper.checkSingularityAccess("universityCourse");
const wasFocusing = player.focus; const wasFocusing = player.focus;
@ -365,7 +350,10 @@ export function NetscriptSingularity(
return true; return true;
}, },
gymWorkout: function (gymName: any, stat: any, focus = true): any { gymWorkout: function (_gymName: unknown, _stat: unknown, _focus: unknown = true): boolean {
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.updateDynamicRam("gymWorkout", getRamCost(player, "gymWorkout"));
helper.checkSingularityAccess("gymWorkout"); helper.checkSingularityAccess("gymWorkout");
const wasFocusing = player.focus; const wasFocusing = player.focus;
@ -477,11 +465,12 @@ export function NetscriptSingularity(
return true; return true;
}, },
travelToCity: function (cityname: any): any { travelToCity: function (_cityName: unknown): boolean {
const cityName = helper.city("travelToCity", "cityName", _cityName);
helper.updateDynamicRam("travelToCity", getRamCost(player, "travelToCity")); helper.updateDynamicRam("travelToCity", getRamCost(player, "travelToCity"));
helper.checkSingularityAccess("travelToCity"); helper.checkSingularityAccess("travelToCity");
switch (cityname) { switch (cityName) {
case CityName.Aevum: case CityName.Aevum:
case CityName.Chongqing: case CityName.Chongqing:
case CityName.Sector12: case CityName.Sector12:
@ -493,16 +482,16 @@ export function NetscriptSingularity(
return false; return false;
} }
player.loseMoney(CONSTANTS.TravelCost, "other"); player.loseMoney(CONSTANTS.TravelCost, "other");
player.city = cityname; player.city = cityName;
workerScript.log("travelToCity", () => `Traveled to ${cityname}`); workerScript.log("travelToCity", () => `Traveled to ${cityName}`);
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000);
return true; return true;
default: default:
throw helper.makeRuntimeErrorMsg("travelToCity", `Invalid city name: '${cityname}'.`); throw helper.makeRuntimeErrorMsg("travelToCity", `Invalid city name: '${cityName}'.`);
} }
}, },
purchaseTor: function (): any { purchaseTor: function (): boolean {
helper.updateDynamicRam("purchaseTor", getRamCost(player, "purchaseTor")); helper.updateDynamicRam("purchaseTor", getRamCost(player, "purchaseTor"));
helper.checkSingularityAccess("purchaseTor"); helper.checkSingularityAccess("purchaseTor");
@ -534,7 +523,8 @@ export function NetscriptSingularity(
workerScript.log("purchaseTor", () => "You have purchased a Tor router!"); workerScript.log("purchaseTor", () => "You have purchased a Tor router!");
return true; return true;
}, },
purchaseProgram: function (programName: any): any { purchaseProgram: function (_programName: unknown): boolean {
const programName = helper.string("purchaseProgram", "programName", _programName).toLowerCase();
helper.updateDynamicRam("purchaseProgram", getRamCost(player, "purchaseProgram")); helper.updateDynamicRam("purchaseProgram", getRamCost(player, "purchaseProgram"));
helper.checkSingularityAccess("purchaseProgram"); helper.checkSingularityAccess("purchaseProgram");
@ -543,8 +533,6 @@ export function NetscriptSingularity(
return false; return false;
} }
programName = programName.toLowerCase();
const item = Object.values(DarkWebItems).find((i) => i.program.toLowerCase() === programName); const item = Object.values(DarkWebItems).find((i) => i.program.toLowerCase() === programName);
if (item == null) { if (item == null) {
workerScript.log("purchaseProgram", () => `Invalid program name: '${programName}.`); workerScript.log("purchaseProgram", () => `Invalid program name: '${programName}.`);
@ -573,12 +561,13 @@ export function NetscriptSingularity(
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 5000); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 5000);
return true; return true;
}, },
getCurrentServer: function (): any { getCurrentServer: function (): string {
helper.updateDynamicRam("getCurrentServer", getRamCost(player, "getCurrentServer")); helper.updateDynamicRam("getCurrentServer", getRamCost(player, "getCurrentServer"));
helper.checkSingularityAccess("getCurrentServer"); helper.checkSingularityAccess("getCurrentServer");
return player.getCurrentServer().hostname; return player.getCurrentServer().hostname;
}, },
connect: function (hostname: any): any { connect: function (_hostname: unknown): boolean {
const hostname = helper.string("purchaseProgram", "hostname", _hostname);
helper.updateDynamicRam("connect", getRamCost(player, "connect")); helper.updateDynamicRam("connect", getRamCost(player, "connect"));
helper.checkSingularityAccess("connect"); helper.checkSingularityAccess("connect");
if (!hostname) { if (!hostname) {
@ -613,13 +602,13 @@ export function NetscriptSingularity(
return false; return false;
}, },
manualHack: function (): any { manualHack: function (): Promise<number> {
helper.updateDynamicRam("manualHack", getRamCost(player, "manualHack")); helper.updateDynamicRam("manualHack", getRamCost(player, "manualHack"));
helper.checkSingularityAccess("manualHack"); helper.checkSingularityAccess("manualHack");
const server = player.getCurrentServer(); const server = player.getCurrentServer();
return helper.hack(server.hostname, true); return helper.hack(server.hostname, true);
}, },
installBackdoor: function (): any { installBackdoor: function (): Promise<void> {
helper.updateDynamicRam("installBackdoor", getRamCost(player, "installBackdoor")); helper.updateDynamicRam("installBackdoor", getRamCost(player, "installBackdoor"));
helper.checkSingularityAccess("installBackdoor"); helper.checkSingularityAccess("installBackdoor");
const baseserver = player.getCurrentServer(); const baseserver = player.getCurrentServer();
@ -657,8 +646,8 @@ export function NetscriptSingularity(
helper.checkSingularityAccess("isFocused"); helper.checkSingularityAccess("isFocused");
return player.focus; return player.focus;
}, },
setFocus: function (afocus: any): boolean { setFocus: function (_focus: unknown): boolean {
const focus = helper.boolean(afocus); const focus = helper.boolean(_focus);
helper.updateDynamicRam("setFocus", getRamCost(player, "setFocus")); helper.updateDynamicRam("setFocus", getRamCost(player, "setFocus"));
helper.checkSingularityAccess("setFocus"); helper.checkSingularityAccess("setFocus");
if (!player.isWorking) { if (!player.isWorking) {
@ -686,7 +675,7 @@ export function NetscriptSingularity(
} }
return false; return false;
}, },
getStats: function (): any { getStats: function (): PlayerSkills {
helper.updateDynamicRam("getStats", getRamCost(player, "getStats")); helper.updateDynamicRam("getStats", getRamCost(player, "getStats"));
helper.checkSingularityAccess("getStats"); helper.checkSingularityAccess("getStats");
workerScript.log("getStats", () => `getStats is deprecated, please use getplayer`); workerScript.log("getStats", () => `getStats is deprecated, please use getplayer`);
@ -701,7 +690,7 @@ export function NetscriptSingularity(
intelligence: player.intelligence, intelligence: player.intelligence,
}; };
}, },
getCharacterInformation: function (): any { getCharacterInformation: function (): CharacterInfo {
helper.updateDynamicRam("getCharacterInformation", getRamCost(player, "getCharacterInformation")); helper.updateDynamicRam("getCharacterInformation", getRamCost(player, "getCharacterInformation"));
helper.checkSingularityAccess("getCharacterInformation"); helper.checkSingularityAccess("getCharacterInformation");
workerScript.log("getCharacterInformation", () => `getCharacterInformation is deprecated, please use getplayer`); workerScript.log("getCharacterInformation", () => `getCharacterInformation is deprecated, please use getplayer`);
@ -717,6 +706,8 @@ export function NetscriptSingularity(
mult: { mult: {
agility: player.agility_mult, agility: player.agility_mult,
agilityExp: player.agility_exp_mult, agilityExp: player.agility_exp_mult,
charisma: player.charisma,
charismaExp: player.charisma_exp,
companyRep: player.company_rep_mult, companyRep: player.company_rep_mult,
crimeMoney: player.crime_money_mult, crimeMoney: player.crime_money_mult,
crimeSuccess: player.crime_success_mult, crimeSuccess: player.crime_success_mult,
@ -749,21 +740,21 @@ export function NetscriptSingularity(
charismaExp: player.charisma_exp, charismaExp: player.charisma_exp,
}; };
}, },
hospitalize: function (): any { hospitalize: function (): void {
helper.updateDynamicRam("hospitalize", getRamCost(player, "hospitalize")); helper.updateDynamicRam("hospitalize", getRamCost(player, "hospitalize"));
helper.checkSingularityAccess("hospitalize"); helper.checkSingularityAccess("hospitalize");
if (player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse) { if (player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse) {
workerScript.log("hospitalize", () => "Cannot go to the hospital because the player is busy."); workerScript.log("hospitalize", () => "Cannot go to the hospital because the player is busy.");
return; return;
} }
return player.hospitalize(); player.hospitalize();
}, },
isBusy: function (): any { isBusy: function (): boolean {
helper.updateDynamicRam("isBusy", getRamCost(player, "isBusy")); helper.updateDynamicRam("isBusy", getRamCost(player, "isBusy"));
helper.checkSingularityAccess("isBusy"); helper.checkSingularityAccess("isBusy");
return player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse; return player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse;
}, },
stopAction: function (): any { stopAction: function (): boolean {
helper.updateDynamicRam("stopAction", getRamCost(player, "stopAction")); helper.updateDynamicRam("stopAction", getRamCost(player, "stopAction"));
helper.checkSingularityAccess("stopAction"); helper.checkSingularityAccess("stopAction");
if (player.isWorking) { if (player.isWorking) {
@ -777,7 +768,7 @@ export function NetscriptSingularity(
} }
return false; return false;
}, },
upgradeHomeCores: function (): any { upgradeHomeCores: function (): boolean {
helper.updateDynamicRam("upgradeHomeCores", getRamCost(player, "upgradeHomeCores")); helper.updateDynamicRam("upgradeHomeCores", getRamCost(player, "upgradeHomeCores"));
helper.checkSingularityAccess("upgradeHomeCores"); helper.checkSingularityAccess("upgradeHomeCores");
@ -807,13 +798,13 @@ export function NetscriptSingularity(
); );
return true; return true;
}, },
getUpgradeHomeCoresCost: function (): any { getUpgradeHomeCoresCost: function (): number {
helper.updateDynamicRam("getUpgradeHomeCoresCost", getRamCost(player, "getUpgradeHomeCoresCost")); helper.updateDynamicRam("getUpgradeHomeCoresCost", getRamCost(player, "getUpgradeHomeCoresCost"));
helper.checkSingularityAccess("getUpgradeHomeCoresCost"); helper.checkSingularityAccess("getUpgradeHomeCoresCost");
return player.getUpgradeHomeCoresCost(); return player.getUpgradeHomeCoresCost();
}, },
upgradeHomeRam: function (): any { upgradeHomeRam: function (): boolean {
helper.updateDynamicRam("upgradeHomeRam", getRamCost(player, "upgradeHomeRam")); helper.updateDynamicRam("upgradeHomeRam", getRamCost(player, "upgradeHomeRam"));
helper.checkSingularityAccess("upgradeHomeRam"); helper.checkSingularityAccess("upgradeHomeRam");
@ -846,13 +837,15 @@ export function NetscriptSingularity(
); );
return true; return true;
}, },
getUpgradeHomeRamCost: function (): any { getUpgradeHomeRamCost: function (): number {
helper.updateDynamicRam("getUpgradeHomeRamCost", getRamCost(player, "getUpgradeHomeRamCost")); helper.updateDynamicRam("getUpgradeHomeRamCost", getRamCost(player, "getUpgradeHomeRamCost"));
helper.checkSingularityAccess("getUpgradeHomeRamCost"); helper.checkSingularityAccess("getUpgradeHomeRamCost");
return player.getUpgradeHomeRamCost(); return player.getUpgradeHomeRamCost();
}, },
workForCompany: function (companyName: any, focus = true): any { workForCompany: function (_companyName: unknown, _focus: unknown = true): boolean {
let companyName = helper.string("workForCompany", "companyName", _companyName);
const focus = helper.boolean(_focus);
helper.updateDynamicRam("workForCompany", getRamCost(player, "workForCompany")); helper.updateDynamicRam("workForCompany", getRamCost(player, "workForCompany"));
helper.checkSingularityAccess("workForCompany"); helper.checkSingularityAccess("workForCompany");
@ -906,12 +899,14 @@ export function NetscriptSingularity(
); );
return true; return true;
}, },
applyToCompany: function (companyName: any, field: any): any { applyToCompany: function (_companyName: unknown, _field: unknown): boolean {
const companyName = helper.string("applyToCompany", "companyName", _companyName);
const field = helper.string("applyToCompany", "field", _field);
helper.updateDynamicRam("applyToCompany", getRamCost(player, "applyToCompany")); helper.updateDynamicRam("applyToCompany", getRamCost(player, "applyToCompany"));
helper.checkSingularityAccess("applyToCompany"); helper.checkSingularityAccess("applyToCompany");
getCompany("applyToCompany", companyName); getCompany("applyToCompany", companyName);
player.location = companyName; player.location = companyName as LocationName;
let res; let res;
switch (field.toLowerCase()) { switch (field.toLowerCase()) {
case "software": case "software":
@ -976,66 +971,73 @@ export function NetscriptSingularity(
} }
return res; return res;
}, },
getCompanyRep: function (companyName: any): any { getCompanyRep: function (_companyName: unknown): number {
const companyName = helper.string("getCompanyRep", "companyName", _companyName);
helper.updateDynamicRam("getCompanyRep", getRamCost(player, "getCompanyRep")); helper.updateDynamicRam("getCompanyRep", getRamCost(player, "getCompanyRep"));
helper.checkSingularityAccess("getCompanyRep"); helper.checkSingularityAccess("getCompanyRep");
const company = getCompany("getCompanyRep", companyName); const company = getCompany("getCompanyRep", companyName);
return company.playerReputation; return company.playerReputation;
}, },
getCompanyFavor: function (companyName: any): any { getCompanyFavor: function (_companyName: unknown): number {
const companyName = helper.string("getCompanyFavor", "companyName", _companyName);
helper.updateDynamicRam("getCompanyFavor", getRamCost(player, "getCompanyFavor")); helper.updateDynamicRam("getCompanyFavor", getRamCost(player, "getCompanyFavor"));
helper.checkSingularityAccess("getCompanyFavor"); helper.checkSingularityAccess("getCompanyFavor");
const company = getCompany("getCompanyFavor", companyName); const company = getCompany("getCompanyFavor", companyName);
return company.favor; return company.favor;
}, },
getCompanyFavorGain: function (companyName: any): any { getCompanyFavorGain: function (_companyName: unknown): number {
const companyName = helper.string("getCompanyFavorGain", "companyName", _companyName);
helper.updateDynamicRam("getCompanyFavorGain", getRamCost(player, "getCompanyFavorGain")); helper.updateDynamicRam("getCompanyFavorGain", getRamCost(player, "getCompanyFavorGain"));
helper.checkSingularityAccess("getCompanyFavorGain"); helper.checkSingularityAccess("getCompanyFavorGain");
const company = getCompany("getCompanyFavorGain", companyName); const company = getCompany("getCompanyFavorGain", companyName);
return company.getFavorGain(); return company.getFavorGain();
}, },
checkFactionInvitations: function (): any { checkFactionInvitations: function (): string[] {
helper.updateDynamicRam("checkFactionInvitations", getRamCost(player, "checkFactionInvitations")); helper.updateDynamicRam("checkFactionInvitations", getRamCost(player, "checkFactionInvitations"));
helper.checkSingularityAccess("checkFactionInvitations"); helper.checkSingularityAccess("checkFactionInvitations");
// Make a copy of player.factionInvitations // Make a copy of player.factionInvitations
return player.factionInvitations.slice(); return player.factionInvitations.slice();
}, },
joinFaction: function (name: any): any { joinFaction: function (_facName: unknown): boolean {
const facName = helper.string("joinFaction", "facName", _facName);
helper.updateDynamicRam("joinFaction", getRamCost(player, "joinFaction")); helper.updateDynamicRam("joinFaction", getRamCost(player, "joinFaction"));
helper.checkSingularityAccess("joinFaction"); helper.checkSingularityAccess("joinFaction");
getFaction("joinFaction", name); getFaction("joinFaction", facName);
if (!player.factionInvitations.includes(name)) { if (!player.factionInvitations.includes(facName)) {
workerScript.log("joinFaction", () => `You have not been invited by faction '${name}'`); workerScript.log("joinFaction", () => `You have not been invited by faction '${facName}'`);
return false; return false;
} }
const fac = Factions[name]; const fac = Factions[facName];
joinFaction(fac); joinFaction(fac);
// Update Faction Invitation list to account for joined + banned factions // Update Faction Invitation list to account for joined + banned factions
for (let i = 0; i < player.factionInvitations.length; ++i) { for (let i = 0; i < player.factionInvitations.length; ++i) {
if (player.factionInvitations[i] == name || Factions[player.factionInvitations[i]].isBanned) { if (player.factionInvitations[i] == facName || Factions[player.factionInvitations[i]].isBanned) {
player.factionInvitations.splice(i, 1); player.factionInvitations.splice(i, 1);
i--; i--;
} }
} }
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 5); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 5);
workerScript.log("joinFaction", () => `Joined the '${name}' faction.`); workerScript.log("joinFaction", () => `Joined the '${facName}' faction.`);
return true; return true;
}, },
workForFaction: function (name: any, type: any, focus = true): any { workForFaction: function (_facName: unknown, _type: unknown, _focus: unknown = true): boolean {
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.updateDynamicRam("workForFaction", getRamCost(player, "workForFaction"));
helper.checkSingularityAccess("workForFaction"); helper.checkSingularityAccess("workForFaction");
getFaction("workForFaction", name); getFaction("workForFaction", facName);
// if the player is in a gang and the target faction is any of the gang faction, fail // if the player is in a gang and the target faction is any of the gang faction, fail
if (player.inGang() && AllGangs[name] !== undefined) { if (player.inGang() && AllGangs[facName] !== undefined) {
workerScript.log("workForFaction", () => `Faction '${name}' does not offer work at the moment.`); workerScript.log("workForFaction", () => `Faction '${facName}' does not offer work at the moment.`);
return false; return false;
} }
if (!player.factions.includes(name)) { if (!player.factions.includes(facName)) {
workerScript.log("workForFaction", () => `You are not a member of '${name}'`); workerScript.log("workForFaction", () => `You are not a member of '${facName}'`);
return false; return false;
} }
@ -1045,7 +1047,7 @@ export function NetscriptSingularity(
workerScript.log("workForFaction", () => txt); workerScript.log("workForFaction", () => txt);
} }
const fac = Factions[name]; const fac = Factions[facName];
// Arrays listing factions that allow each time of work // Arrays listing factions that allow each time of work
switch (type.toLowerCase()) { switch (type.toLowerCase()) {
@ -1105,34 +1107,42 @@ export function NetscriptSingularity(
} }
return true; return true;
}, },
getFactionRep: function (name: any): any { getFactionRep: function (_facName: unknown): number {
const facName = helper.string("getFactionRep", "facName", _facName);
helper.updateDynamicRam("getFactionRep", getRamCost(player, "getFactionRep")); helper.updateDynamicRam("getFactionRep", getRamCost(player, "getFactionRep"));
helper.checkSingularityAccess("getFactionRep"); helper.checkSingularityAccess("getFactionRep");
const faction = getFaction("getFactionRep", name); const faction = getFaction("getFactionRep", facName);
return faction.playerReputation; return faction.playerReputation;
}, },
getFactionFavor: function (name: any): any { getFactionFavor: function (_facName: unknown): number {
const facName = helper.string("getFactionRep", "facName", _facName);
helper.updateDynamicRam("getFactionFavor", getRamCost(player, "getFactionFavor")); helper.updateDynamicRam("getFactionFavor", getRamCost(player, "getFactionFavor"));
helper.checkSingularityAccess("getFactionFavor"); helper.checkSingularityAccess("getFactionFavor");
const faction = getFaction("getFactionFavor", name); const faction = getFaction("getFactionFavor", facName);
return faction.favor; return faction.favor;
}, },
getFactionFavorGain: function (name: any): any { getFactionFavorGain: function (_facName: unknown): number {
const facName = helper.string("getFactionFavorGain", "facName", _facName);
helper.updateDynamicRam("getFactionFavorGain", getRamCost(player, "getFactionFavorGain")); helper.updateDynamicRam("getFactionFavorGain", getRamCost(player, "getFactionFavorGain"));
helper.checkSingularityAccess("getFactionFavorGain"); helper.checkSingularityAccess("getFactionFavorGain");
const faction = getFaction("getFactionFavorGain", name); const faction = getFaction("getFactionFavorGain", facName);
return faction.getFavorGain(); return faction.getFavorGain();
}, },
donateToFaction: function (name: any, amt: any): any { donateToFaction: function (_facName: unknown, _amt: unknown): boolean {
const facName = helper.string("donateToFaction", "facName", _facName);
const amt = helper.number("donateToFaction", "amt", _amt);
helper.updateDynamicRam("donateToFaction", getRamCost(player, "donateToFaction")); helper.updateDynamicRam("donateToFaction", getRamCost(player, "donateToFaction"));
helper.checkSingularityAccess("donateToFaction"); helper.checkSingularityAccess("donateToFaction");
const faction = getFaction("donateToFaction", name); const faction = getFaction("donateToFaction", facName);
if (!player.factions.includes(faction.name)) { if (!player.factions.includes(faction.name)) {
workerScript.log("donateToFaction", () => `You can't donate to '${name}' because you aren't a member`); workerScript.log("donateToFaction", () => `You can't donate to '${facName}' because you aren't a member`);
return false; return false;
} }
if (player.inGang() && faction.name === player.getGangFaction().name) { if (player.inGang() && faction.name === player.getGangFaction().name) {
workerScript.log("donateToFaction", () => `You can't donate to '${name}' because youre managing a gang for it`); workerScript.log(
"donateToFaction",
() => `You can't donate to '${facName}' because youre managing a gang for it`,
);
return false; return false;
} }
if (typeof amt !== "number" || amt <= 0 || isNaN(amt)) { if (typeof amt !== "number" || amt <= 0 || isNaN(amt)) {
@ -1142,7 +1152,7 @@ export function NetscriptSingularity(
if (player.money < amt) { if (player.money < amt) {
workerScript.log( workerScript.log(
"donateToFaction", "donateToFaction",
() => `You do not have enough money to donate ${numeralWrapper.formatMoney(amt)} to '${name}'`, () => `You do not have enough money to donate ${numeralWrapper.formatMoney(amt)} to '${facName}'`,
); );
return false; return false;
} }
@ -1161,13 +1171,15 @@ export function NetscriptSingularity(
workerScript.log( workerScript.log(
"donateToFaction", "donateToFaction",
() => () =>
`${numeralWrapper.formatMoney(amt)} donated to '${name}' for ${numeralWrapper.formatReputation( `${numeralWrapper.formatMoney(amt)} donated to '${facName}' for ${numeralWrapper.formatReputation(
repGain, repGain,
)} reputation`, )} reputation`,
); );
return true; return true;
}, },
createProgram: function (name: any, focus = true): any { createProgram: function (_programName: unknown, _focus: unknown = true): boolean {
const programName = helper.string("createProgram", "programName", _programName).toLowerCase();
const focus = helper.boolean(_focus);
helper.updateDynamicRam("createProgram", getRamCost(player, "createProgram")); helper.updateDynamicRam("createProgram", getRamCost(player, "createProgram"));
helper.checkSingularityAccess("createProgram"); helper.checkSingularityAccess("createProgram");
@ -1177,12 +1189,10 @@ export function NetscriptSingularity(
workerScript.log("createProgram", () => txt); workerScript.log("createProgram", () => txt);
} }
name = name.toLowerCase(); const p = Object.values(Programs).find((p) => p.name.toLowerCase() === programName);
const p = Object.values(Programs).find((p) => p.name.toLowerCase() === name);
if (p == null) { if (p == null) {
workerScript.log("createProgram", () => `The specified program does not exist: '${name}`); workerScript.log("createProgram", () => `The specified program does not exist: '${programName}`);
return false; return false;
} }
@ -1213,10 +1223,11 @@ export function NetscriptSingularity(
player.stopFocusing(); player.stopFocusing();
Router.toTerminal(); Router.toTerminal();
} }
workerScript.log("createProgram", () => `Began creating program: '${name}'`); workerScript.log("createProgram", () => `Began creating program: '${programName}'`);
return true; return true;
}, },
commitCrime: function (crimeRoughName: any): any { commitCrime: function (_crimeRoughName: unknown): number {
const crimeRoughName = helper.string("commitCrime", "crimeRoughName", _crimeRoughName);
helper.updateDynamicRam("commitCrime", getRamCost(player, "commitCrime")); helper.updateDynamicRam("commitCrime", getRamCost(player, "commitCrime"));
helper.checkSingularityAccess("commitCrime"); helper.checkSingularityAccess("commitCrime");
@ -1236,7 +1247,8 @@ export function NetscriptSingularity(
workerScript.log("commitCrime", () => `Attempting to commit ${crime.name}...`); workerScript.log("commitCrime", () => `Attempting to commit ${crime.name}...`);
return crime.commit(Router, player, 1, workerScript); return crime.commit(Router, player, 1, workerScript);
}, },
getCrimeChance: function (crimeRoughName: any): any { getCrimeChance: function (_crimeRoughName: unknown): number {
const crimeRoughName = helper.string("getCrimeChance", "crimeRoughName", _crimeRoughName);
helper.updateDynamicRam("getCrimeChance", getRamCost(player, "getCrimeChance")); helper.updateDynamicRam("getCrimeChance", getRamCost(player, "getCrimeChance"));
helper.checkSingularityAccess("getCrimeChance"); helper.checkSingularityAccess("getCrimeChance");
@ -1247,7 +1259,8 @@ export function NetscriptSingularity(
return crime.successRate(player); return crime.successRate(player);
}, },
getCrimeStats: function (crimeRoughName: any): any { getCrimeStats: function (_crimeRoughName: unknown): CrimeStats {
const crimeRoughName = helper.string("getCrimeStats", "crimeRoughName", _crimeRoughName);
helper.updateDynamicRam("getCrimeStats", getRamCost(player, "getCrimeStats")); helper.updateDynamicRam("getCrimeStats", getRamCost(player, "getCrimeStats"));
helper.checkSingularityAccess("getCrimeStats"); helper.checkSingularityAccess("getCrimeStats");
@ -1269,7 +1282,8 @@ export function NetscriptSingularity(
} }
return Object.values(DarkWebItems).map((p) => p.program); return Object.values(DarkWebItems).map((p) => p.program);
}, },
getDarkwebProgramCost: function (programName: any): any { getDarkwebProgramCost: function (_programName: unknown): number {
const programName = helper.string("getDarkwebProgramCost", "programName", _programName).toLowerCase();
helper.updateDynamicRam("getDarkwebProgramCost", getRamCost(player, "getDarkwebProgramCost")); helper.updateDynamicRam("getDarkwebProgramCost", getRamCost(player, "getDarkwebProgramCost"));
helper.checkSingularityAccess("getDarkwebProgramCost"); helper.checkSingularityAccess("getDarkwebProgramCost");
@ -1281,7 +1295,6 @@ export function NetscriptSingularity(
return -1; return -1;
} }
programName = programName.toLowerCase();
const item = Object.values(DarkWebItems).find((i) => i.program.toLowerCase() === programName); const item = Object.values(DarkWebItems).find((i) => i.program.toLowerCase() === programName);
// If the program doesn't exist, throw an error. The reasoning here is that the 99% case is that // If the program doesn't exist, throw an error. The reasoning here is that the 99% case is that

@ -10,10 +10,16 @@ import { Augmentations } from "../Augmentation/Augmentations";
import { CityName } from "../Locations/data/CityNames"; import { CityName } from "../Locations/data/CityNames";
import { findCrime } from "../Crime/CrimeHelpers"; import { findCrime } from "../Crime/CrimeHelpers";
import { Sleeve as ISleeve } from "../ScriptEditor/NetscriptDefinitions"; import {
AugmentPair,
Sleeve as ISleeve,
SleeveInformation,
SleeveSkills,
SleeveTask,
} from "../ScriptEditor/NetscriptDefinitions";
export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): ISleeve { export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): ISleeve {
const checkSleeveAPIAccess = function (func: any): void { const checkSleeveAPIAccess = function (func: string): void {
if (player.bitNodeN !== 10 && !SourceFileFlags[10]) { if (player.bitNodeN !== 10 && !SourceFileFlags[10]) {
throw helper.makeRuntimeErrorMsg( throw helper.makeRuntimeErrorMsg(
`sleeve.${func}`, `sleeve.${func}`,
@ -22,7 +28,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
} }
}; };
const checkSleeveNumber = function (func: any, sleeveNumber: any): void { const checkSleeveNumber = function (func: string, sleeveNumber: number): void {
if (sleeveNumber >= player.sleeves.length || sleeveNumber < 0) { if (sleeveNumber >= player.sleeves.length || sleeveNumber < 0) {
const msg = `Invalid sleeve number: ${sleeveNumber}`; const msg = `Invalid sleeve number: ${sleeveNumber}`;
workerScript.log(func, () => msg); workerScript.log(func, () => msg);
@ -30,7 +36,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
} }
}; };
const getSleeveStats = function (sleeveNumber: any): any { const getSleeveStats = function (sleeveNumber: number): SleeveSkills {
const sl = player.sleeves[sleeveNumber]; const sl = player.sleeves[sleeveNumber];
return { return {
shock: 100 - sl.shock, shock: 100 - sl.shock,
@ -42,7 +48,7 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
agility: sl.agility, agility: sl.agility,
charisma: sl.charisma, charisma: sl.charisma,
}; };
} };
return { return {
getNumSleeves: function (): number { getNumSleeves: function (): number {
@ -50,23 +56,23 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
checkSleeveAPIAccess("getNumSleeves"); checkSleeveAPIAccess("getNumSleeves");
return player.sleeves.length; return player.sleeves.length;
}, },
setToShockRecovery: function (asleeveNumber: any = 0): boolean { setToShockRecovery: function (_sleeveNumber: unknown): boolean {
const sleeveNumber = helper.number("setToShockRecovery", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("setToShockRecovery", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("setToShockRecovery", getRamCost(player, "sleeve", "setToShockRecovery")); helper.updateDynamicRam("setToShockRecovery", getRamCost(player, "sleeve", "setToShockRecovery"));
checkSleeveAPIAccess("setToShockRecovery"); checkSleeveAPIAccess("setToShockRecovery");
checkSleeveNumber("setToShockRecovery", sleeveNumber); checkSleeveNumber("setToShockRecovery", sleeveNumber);
return player.sleeves[sleeveNumber].shockRecovery(player); return player.sleeves[sleeveNumber].shockRecovery(player);
}, },
setToSynchronize: function (asleeveNumber: any = 0): boolean { setToSynchronize: function (_sleeveNumber: unknown): boolean {
const sleeveNumber = helper.number("setToSynchronize", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("setToSynchronize", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("setToSynchronize", getRamCost(player, "sleeve", "setToSynchronize")); helper.updateDynamicRam("setToSynchronize", getRamCost(player, "sleeve", "setToSynchronize"));
checkSleeveAPIAccess("setToSynchronize"); checkSleeveAPIAccess("setToSynchronize");
checkSleeveNumber("setToSynchronize", sleeveNumber); checkSleeveNumber("setToSynchronize", sleeveNumber);
return player.sleeves[sleeveNumber].synchronize(player); return player.sleeves[sleeveNumber].synchronize(player);
}, },
setToCommitCrime: function (asleeveNumber: any = 0, aCrimeRoughName: any = ""): boolean { setToCommitCrime: function (_sleeveNumber: unknown, _crimeRoughName: unknown): boolean {
const sleeveNumber = helper.number("setToCommitCrime", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("setToCommitCrime", "sleeveNumber", _sleeveNumber);
const crimeRoughName = helper.string("setToCommitCrime", "crimeName", aCrimeRoughName); const crimeRoughName = helper.string("setToCommitCrime", "crimeName", _crimeRoughName);
helper.updateDynamicRam("setToCommitCrime", getRamCost(player, "sleeve", "setToCommitCrime")); helper.updateDynamicRam("setToCommitCrime", getRamCost(player, "sleeve", "setToCommitCrime"));
checkSleeveAPIAccess("setToCommitCrime"); checkSleeveAPIAccess("setToCommitCrime");
checkSleeveNumber("setToCommitCrime", sleeveNumber); checkSleeveNumber("setToCommitCrime", sleeveNumber);
@ -76,25 +82,25 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
} }
return player.sleeves[sleeveNumber].commitCrime(player, crime.name); return player.sleeves[sleeveNumber].commitCrime(player, crime.name);
}, },
setToUniversityCourse: function (asleeveNumber: any = 0, auniversityName: any = "", aclassName: any = ""): boolean { setToUniversityCourse: function (_sleeveNumber: unknown, _universityName: unknown, _className: unknown): boolean {
const sleeveNumber = helper.number("setToUniversityCourse", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("setToUniversityCourse", "sleeveNumber", _sleeveNumber);
const universityName = helper.string("setToUniversityCourse", "universityName", auniversityName); const universityName = helper.string("setToUniversityCourse", "universityName", _universityName);
const className = helper.string("setToUniversityCourse", "className", aclassName); const className = helper.string("setToUniversityCourse", "className", _className);
helper.updateDynamicRam("setToUniversityCourse", getRamCost(player, "sleeve", "setToUniversityCourse")); helper.updateDynamicRam("setToUniversityCourse", getRamCost(player, "sleeve", "setToUniversityCourse"));
checkSleeveAPIAccess("setToUniversityCourse"); checkSleeveAPIAccess("setToUniversityCourse");
checkSleeveNumber("setToUniversityCourse", sleeveNumber); checkSleeveNumber("setToUniversityCourse", sleeveNumber);
return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className); return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className);
}, },
travel: function (asleeveNumber: any = 0, acityName: any = ""): boolean { travel: function (_sleeveNumber: unknown, _cityName: unknown): boolean {
const sleeveNumber = helper.number("travel", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("travel", "sleeveNumber", _sleeveNumber);
const cityName = helper.string("setToUniversityCourse", "cityName", acityName); const cityName = helper.string("setToUniversityCourse", "cityName", _cityName);
helper.updateDynamicRam("travel", getRamCost(player, "sleeve", "travel")); helper.updateDynamicRam("travel", getRamCost(player, "sleeve", "travel"));
checkSleeveAPIAccess("travel"); checkSleeveAPIAccess("travel");
checkSleeveNumber("travel", sleeveNumber); checkSleeveNumber("travel", sleeveNumber);
return player.sleeves[sleeveNumber].travel(player, cityName as CityName); return player.sleeves[sleeveNumber].travel(player, cityName as CityName);
}, },
setToCompanyWork: function (asleeveNumber: any = 0, acompanyName: any = ""): boolean { setToCompanyWork: function (_sleeveNumber: unknown, acompanyName: unknown): boolean {
const sleeveNumber = helper.number("setToCompanyWork", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("setToCompanyWork", "sleeveNumber", _sleeveNumber);
const companyName = helper.string("setToUniversityCourse", "companyName", acompanyName); const companyName = helper.string("setToUniversityCourse", "companyName", acompanyName);
helper.updateDynamicRam("setToCompanyWork", getRamCost(player, "sleeve", "setToCompanyWork")); helper.updateDynamicRam("setToCompanyWork", getRamCost(player, "sleeve", "setToCompanyWork"));
checkSleeveAPIAccess("setToCompanyWork"); checkSleeveAPIAccess("setToCompanyWork");
@ -116,10 +122,10 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
return player.sleeves[sleeveNumber].workForCompany(player, companyName); return player.sleeves[sleeveNumber].workForCompany(player, companyName);
}, },
setToFactionWork: function (asleeveNumber: any = 0, afactionName: any = "", aworkType: any = ""): boolean { setToFactionWork: function (_sleeveNumber: unknown, _factionName: unknown, _workType: unknown): boolean {
const sleeveNumber = helper.number("setToFactionWork", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("setToFactionWork", "sleeveNumber", _sleeveNumber);
const factionName = helper.string("setToUniversityCourse", "factionName", afactionName); const factionName = helper.string("setToUniversityCourse", "factionName", _factionName);
const workType = helper.string("setToUniversityCourse", "workType", aworkType); const workType = helper.string("setToUniversityCourse", "workType", _workType);
helper.updateDynamicRam("setToFactionWork", getRamCost(player, "sleeve", "setToFactionWork")); helper.updateDynamicRam("setToFactionWork", getRamCost(player, "sleeve", "setToFactionWork"));
checkSleeveAPIAccess("setToFactionWork"); checkSleeveAPIAccess("setToFactionWork");
checkSleeveNumber("setToFactionWork", sleeveNumber); checkSleeveNumber("setToFactionWork", sleeveNumber);
@ -140,40 +146,25 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
return player.sleeves[sleeveNumber].workForFaction(player, factionName, workType); return player.sleeves[sleeveNumber].workForFaction(player, factionName, workType);
}, },
setToGymWorkout: function (asleeveNumber: any = 0, agymName: any = "", astat: any = ""): boolean { setToGymWorkout: function (_sleeveNumber: unknown, _gymName: unknown, _stat: unknown): boolean {
const sleeveNumber = helper.number("setToGymWorkout", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("setToGymWorkout", "sleeveNumber", _sleeveNumber);
const gymName = helper.string("setToUniversityCourse", "gymName", agymName); const gymName = helper.string("setToUniversityCourse", "gymName", _gymName);
const stat = helper.string("setToUniversityCourse", "stat", astat); const stat = helper.string("setToUniversityCourse", "stat", _stat);
helper.updateDynamicRam("setToGymWorkout", getRamCost(player, "sleeve", "setToGymWorkout")); helper.updateDynamicRam("setToGymWorkout", getRamCost(player, "sleeve", "setToGymWorkout"));
checkSleeveAPIAccess("setToGymWorkout"); checkSleeveAPIAccess("setToGymWorkout");
checkSleeveNumber("setToGymWorkout", sleeveNumber); checkSleeveNumber("setToGymWorkout", sleeveNumber);
return player.sleeves[sleeveNumber].workoutAtGym(player, gymName, stat); return player.sleeves[sleeveNumber].workoutAtGym(player, gymName, stat);
}, },
getSleeveStats: function (asleeveNumber: any = 0): { getSleeveStats: function (_sleeveNumber: unknown): SleeveSkills {
shock: number; const sleeveNumber = helper.number("getSleeveStats", "sleeveNumber", _sleeveNumber);
sync: number;
hacking: number;
strength: number;
defense: number;
dexterity: number;
agility: number;
charisma: number;
} {
const sleeveNumber = helper.number("getSleeveStats", "sleeveNumber", asleeveNumber);
helper.updateDynamicRam("getSleeveStats", getRamCost(player, "sleeve", "getSleeveStats")); helper.updateDynamicRam("getSleeveStats", getRamCost(player, "sleeve", "getSleeveStats"));
checkSleeveAPIAccess("getSleeveStats"); checkSleeveAPIAccess("getSleeveStats");
checkSleeveNumber("getSleeveStats", sleeveNumber); checkSleeveNumber("getSleeveStats", sleeveNumber);
return getSleeveStats(sleeveNumber) return getSleeveStats(sleeveNumber);
}, },
getTask: function (asleeveNumber: any = 0): { getTask: function (_sleeveNumber: unknown): SleeveTask {
task: string; const sleeveNumber = helper.number("getTask", "sleeveNumber", _sleeveNumber);
crime: string;
location: string;
gymStatType: string;
factionWorkType: string;
} {
const sleeveNumber = helper.number("getTask", "sleeveNumber", asleeveNumber);
helper.updateDynamicRam("getTask", getRamCost(player, "sleeve", "getTask")); helper.updateDynamicRam("getTask", getRamCost(player, "sleeve", "getTask"));
checkSleeveAPIAccess("getTask"); checkSleeveAPIAccess("getTask");
checkSleeveNumber("getTask", sleeveNumber); checkSleeveNumber("getTask", sleeveNumber);
@ -187,14 +178,15 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
factionWorkType: FactionWorkType[sl.factionWorkType], factionWorkType: FactionWorkType[sl.factionWorkType],
}; };
}, },
getInformation: function (asleeveNumber: any = 0): any { getInformation: function (_sleeveNumber: unknown): SleeveInformation {
const sleeveNumber = helper.number("getInformation", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("getInformation", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("getInformation", getRamCost(player, "sleeve", "getInformation")); helper.updateDynamicRam("getInformation", getRamCost(player, "sleeve", "getInformation"));
checkSleeveAPIAccess("getInformation"); checkSleeveAPIAccess("getInformation");
checkSleeveNumber("getInformation", sleeveNumber); checkSleeveNumber("getInformation", sleeveNumber);
const sl = player.sleeves[sleeveNumber]; const sl = player.sleeves[sleeveNumber];
return { return {
tor: false,
city: sl.city, city: sl.city,
hp: sl.hp, hp: sl.hp,
jobs: Object.keys(player.jobs), // technically sleeves have the same jobs as the player. jobs: Object.keys(player.jobs), // technically sleeves have the same jobs as the player.
@ -252,8 +244,8 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
workRepGain: sl.getRepGain(player), workRepGain: sl.getRepGain(player),
}; };
}, },
getSleeveAugmentations: function (asleeveNumber: any = 0): string[] { getSleeveAugmentations: function (_sleeveNumber: unknown): string[] {
const sleeveNumber = helper.number("getSleeveAugmentations", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("getSleeveAugmentations", "sleeveNumber", _sleeveNumber);
helper.updateDynamicRam("getSleeveAugmentations", getRamCost(player, "sleeve", "getSleeveAugmentations")); helper.updateDynamicRam("getSleeveAugmentations", getRamCost(player, "sleeve", "getSleeveAugmentations"));
checkSleeveAPIAccess("getSleeveAugmentations"); checkSleeveAPIAccess("getSleeveAugmentations");
checkSleeveNumber("getSleeveAugmentations", sleeveNumber); checkSleeveNumber("getSleeveAugmentations", sleeveNumber);
@ -264,11 +256,8 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
} }
return augs; return augs;
}, },
getSleevePurchasableAugs: function (asleeveNumber: any = 0): { getSleevePurchasableAugs: function (_sleeveNumber: unknown): AugmentPair[] {
name: string; const sleeveNumber = helper.number("getSleevePurchasableAugs", "sleeveNumber", _sleeveNumber);
cost: number;
}[] {
const sleeveNumber = helper.number("getSleevePurchasableAugs", "sleeveNumber", asleeveNumber);
helper.updateDynamicRam("getSleevePurchasableAugs", getRamCost(player, "sleeve", "getSleevePurchasableAugs")); helper.updateDynamicRam("getSleevePurchasableAugs", getRamCost(player, "sleeve", "getSleevePurchasableAugs"));
checkSleeveAPIAccess("getSleevePurchasableAugs"); checkSleeveAPIAccess("getSleevePurchasableAugs");
checkSleeveNumber("getSleevePurchasableAugs", sleeveNumber); checkSleeveNumber("getSleevePurchasableAugs", sleeveNumber);
@ -285,9 +274,9 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
return augs; return augs;
}, },
purchaseSleeveAug: function (asleeveNumber: any = 0, aaugName: any = ""): boolean { purchaseSleeveAug: function (_sleeveNumber: unknown, _augName: unknown): boolean {
const sleeveNumber = helper.number("purchaseSleeveAug", "sleeveNumber", asleeveNumber); const sleeveNumber = helper.number("purchaseSleeveAug", "sleeveNumber", _sleeveNumber);
const augName = helper.string("purchaseSleeveAug", "augName", aaugName); const augName = helper.string("purchaseSleeveAug", "augName", _augName);
helper.updateDynamicRam("purchaseSleeveAug", getRamCost(player, "sleeve", "purchaseSleeveAug")); helper.updateDynamicRam("purchaseSleeveAug", getRamCost(player, "sleeve", "purchaseSleeveAug"));
checkSleeveAPIAccess("purchaseSleeveAug"); checkSleeveAPIAccess("purchaseSleeveAug");
checkSleeveNumber("purchaseSleeveAug", sleeveNumber); checkSleeveNumber("purchaseSleeveAug", sleeveNumber);

@ -26,6 +26,6 @@ export class GraftableAugmentation {
const antiLog = Math.max(sum(Object.values(this.augmentation.mults)), 1); const antiLog = Math.max(sum(Object.values(this.augmentation.mults)), 1);
const mult = Math.log2(antiLog); const mult = Math.log2(antiLog);
return CONSTANTS.AugmentationGraftingTimeBase * mult + CONSTANTS.MillisecondsPerHalfHour; return (CONSTANTS.AugmentationGraftingTimeBase * mult + CONSTANTS.MillisecondsPerHalfHour) / 2;
} }
} }

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

@ -2078,15 +2078,16 @@ export function reapplyAllAugmentations(this: IPlayer, resetMultipliers = true):
this.augmentations[i].name = "Hacknet Node NIC Architecture Neural-Upload"; this.augmentations[i].name = "Hacknet Node NIC Architecture Neural-Upload";
} }
const augName = this.augmentations[i].name; const playerAug = this.augmentations[i];
const augName = playerAug.name;
const aug = Augmentations[augName]; const aug = Augmentations[augName];
if (aug == null) { if (aug == null) {
console.warn(`Invalid augmentation name in Player.reapplyAllAugmentations(). Aug ${augName} will be skipped`); console.warn(`Invalid augmentation name in Player.reapplyAllAugmentations(). Aug ${augName} will be skipped`);
continue; continue;
} }
aug.owned = true; aug.owned = true;
if (aug.name == AugmentationNames.NeuroFluxGovernor) { if (augName == AugmentationNames.NeuroFluxGovernor) {
for (let j = 0; j < aug.level; ++j) { for (let j = 0; j < playerAug.level; ++j) {
applyAugmentation(this.augmentations[i], true); applyAugmentation(this.augmentations[i], true);
} }
continue; continue;

@ -1,5 +1,5 @@
import { FactionNames } from './Faction/data/FactionNames'; import { FactionNames } from "./Faction/data/FactionNames";
import { CityName } from './Locations/data/CityNames'; import { CityName } from "./Locations/data/CityNames";
import { Augmentations } from "./Augmentation/Augmentations"; import { Augmentations } from "./Augmentation/Augmentations";
import { augmentationExists, initAugmentations } from "./Augmentation/AugmentationHelpers"; import { augmentationExists, initAugmentations } from "./Augmentation/AugmentationHelpers";
import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
@ -263,7 +263,7 @@ export function prestigeSourceFile(flume: boolean): void {
homeComp.messages.push(LiteratureNames.CorporationManagementHandbook); homeComp.messages.push(LiteratureNames.CorporationManagementHandbook);
dialogBoxCreate( dialogBoxCreate(
"You received a copy of the Corporation Management Handbook on your home computer. " + "You received a copy of the Corporation Management Handbook on your home computer. " +
"Read it if you need help getting started with Corporations!", "Read it if you need help getting started with Corporations!",
); );
} }

@ -584,7 +584,7 @@ export interface BitNodeMultipliers {
/** Influences the maximum allowed RAM for a purchased server */ /** Influences the maximum allowed RAM for a purchased server */
PurchasedServerMaxRam: number; PurchasedServerMaxRam: number;
/** Influences cost of any purchased server at or above 128GB */ /** Influences cost of any purchased server at or above 128GB */
PurchasedServerSoftCap: number; PurchasedServerSoftcap: number;
/** Influences the minimum favor the player must have with a faction before they can donate to gain rep. */ /** Influences the minimum favor the player must have with a faction before they can donate to gain rep. */
RepToDonateToFaction: number; RepToDonateToFaction: number;
/** Influences how much the money on a server can be reduced when a script performs a hack against it. */ /** Influences how much the money on a server can be reduced when a script performs a hack against it. */
@ -667,6 +667,10 @@ export interface CharacterMult {
agility: number; agility: number;
/** Agility exp */ /** Agility exp */
agilityExp: number; agilityExp: number;
/** Charisma stat */
charisma: number;
/** Charisma exp */
charismaExp: number;
/** Company reputation */ /** Company reputation */
companyRep: number; companyRep: number;
/** Money earned from crimes */ /** Money earned from crimes */
@ -707,10 +711,10 @@ export interface CharacterInfo {
factions: string[]; factions: string[];
/** Current health points */ /** Current health points */
hp: number; hp: number;
/** Array of all companies at which you have jobs */ /** Array of all jobs */
company: string[]; jobs: string[];
/** Array of job positions for all companies you are employed at. Same order as 'jobs' */ /** Array of job positions for all companies you are employed at. Same order as 'jobs' */
jobTitle: string[]; jobTitles: string[];
/** Maximum health points */ /** Maximum health points */
maxHp: number; maxHp: number;
/** Boolean indicating whether or not you have a tor router */ /** Boolean indicating whether or not you have a tor router */
@ -735,6 +739,18 @@ export interface CharacterInfo {
workRepGain: number; workRepGain: number;
/** Money earned so far from work, if applicable */ /** Money earned so far from work, if applicable */
workMoneyGain: number; workMoneyGain: number;
/** total hacking exp */
hackingExp: number;
/** total strength exp */
strengthExp: number;
/** total defense exp */
defenseExp: number;
/** total dexterity exp */
dexterityExp: number;
/** total agility exp */
agilityExp: number;
/** total charisma exp */
charismaExp: number;
} }
/** /**
@ -2199,11 +2215,8 @@ export interface Singularity {
* Hospitalize the player. * Hospitalize the player.
* @remarks * @remarks
* RAM cost: 0.25 GB * 16/4/1 * RAM cost: 0.25 GB * 16/4/1
*
*
* @returns The cost of the hospitalization.
*/ */
hospitalize(): number; hospitalize(): void;
/** /**
* Soft reset the game. * Soft reset the game.
@ -4324,6 +4337,12 @@ export interface NS extends Singularity {
*/ */
readonly ui: UserInterface; readonly ui: UserInterface;
/**
* Namespace for singularity functions.
* RAM cost: 0 GB
*/
readonly singularity: Singularity;
/** /**
* Namespace for grafting functions. * Namespace for grafting functions.
* @remarks * @remarks
@ -5630,7 +5649,7 @@ export interface NS extends Singularity {
* @param args - Arguments to identify the script * @param args - Arguments to identify the script
* @returns The info about the running script if found, and null otherwise. * @returns The info about the running script if found, and null otherwise.
*/ */
getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string | number)[]): RunningScript; getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string | number)[]): RunningScript | null;
/** /**
* Get cost of purchasing a server. * Get cost of purchasing a server.

@ -163,7 +163,7 @@ export class BaseServer {
return false; return false;
} }
removeContract(contract: CodingContract): void { removeContract(contract: CodingContract | string): void {
if (contract instanceof CodingContract) { if (contract instanceof CodingContract) {
this.contracts = this.contracts.filter((c) => { this.contracts = this.contracts.filter((c) => {
return c.fn !== contract.fn; return c.fn !== contract.fn;

@ -276,7 +276,7 @@ export function SidebarRoot(props: IProps): React.ReactElement {
function handleShortcuts(this: Document, event: KeyboardEvent): any { function handleShortcuts(this: Document, event: KeyboardEvent): any {
if (Settings.DisableHotkeys) return; if (Settings.DisableHotkeys) return;
if ((props.player.isWorking && props.player.focus) || redPillFlag) return; if ((props.player.isWorking && props.player.focus) || redPillFlag) return;
if (event.key === "t" && event.altKey) { if (event.key === KEY.T && event.altKey) {
event.preventDefault(); event.preventDefault();
clickTerminal(); clickTerminal();
} else if (event.key === KEY.C && event.altKey) { } else if (event.key === KEY.C && event.altKey) {
@ -522,7 +522,9 @@ export function SidebarRoot(props: IProps): React.ReactElement {
<ListItemIcon> <ListItemIcon>
<Badge badgeContent={invitationsCount !== 0 ? invitationsCount : undefined} color="error"> <Badge badgeContent={invitationsCount !== 0 ? invitationsCount : undefined} color="error">
<Tooltip title={!open ? "Factions" : ""}> <Tooltip title={!open ? "Factions" : ""}>
<ContactsIcon color={![Page.Factions, Page.Faction].includes(props.page) ? "secondary" : "primary"} /> <ContactsIcon
color={![Page.Factions, Page.Faction].includes(props.page) ? "secondary" : "primary"}
/>
</Tooltip> </Tooltip>
</Badge> </Badge>
</ListItemIcon> </ListItemIcon>
@ -570,7 +572,9 @@ export function SidebarRoot(props: IProps): React.ReactElement {
> >
<ListItemIcon> <ListItemIcon>
<Tooltip title={!open ? "Hacknet" : ""}> <Tooltip title={!open ? "Hacknet" : ""}>
<AccountTreeIcon color={flashHacknet ? "error" : props.page !== Page.Hacknet ? "secondary" : "primary"} /> <AccountTreeIcon
color={flashHacknet ? "error" : props.page !== Page.Hacknet ? "secondary" : "primary"}
/>
</Tooltip> </Tooltip>
</ListItemIcon> </ListItemIcon>
<ListItemText> <ListItemText>

@ -1,3 +1,4 @@
import { KEY } from "../utils/helpers/keyCodes";
import { substituteAliases } from "../Alias"; import { substituteAliases } from "../Alias";
// Helper function that checks if an argument (which is a string) is a valid number // Helper function that checks if an argument (which is a string) is a valid number
function isNumber(str: string): boolean { function isNumber(str: string): boolean {
@ -55,11 +56,11 @@ export function ParseCommand(command: string): (string | number | boolean)[] {
} }
const c = command.charAt(i); const c = command.charAt(i);
if (c === '"') { if (c === KEY.DOUBLE_QUOTE) {
// Double quotes // Double quotes
if (!escaped && prevChar === " ") { if (!escaped && prevChar === KEY.SPACE) {
const endQuote = command.indexOf('"', i + 1); const endQuote = command.indexOf(KEY.DOUBLE_QUOTE, i + 1);
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === " ")) { if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
args.push(command.substr(i + 1, endQuote - i - 1)); args.push(command.substr(i + 1, endQuote - i - 1));
if (endQuote === command.length - 1) { if (endQuote === command.length - 1) {
start = i = endQuote + 1; start = i = endQuote + 1;
@ -69,15 +70,15 @@ export function ParseCommand(command: string): (string | number | boolean)[] {
continue; continue;
} }
} else if (inQuote === ``) { } else if (inQuote === ``) {
inQuote = `"`; inQuote = KEY.DOUBLE_QUOTE;
} else if (inQuote === `"`) { } else if (inQuote === KEY.DOUBLE_QUOTE) {
inQuote = ``; inQuote = ``;
} }
} else if (c === "'") { } else if (c === KEY.QUOTE) {
// Single quotes, same thing as above // Single quotes, same thing as above
if (!escaped && prevChar === " ") { if (!escaped && prevChar === KEY.SPACE) {
const endQuote = command.indexOf("'", i + 1); const endQuote = command.indexOf(KEY.QUOTE, i + 1);
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === " ")) { if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
args.push(command.substr(i + 1, endQuote - i - 1)); args.push(command.substr(i + 1, endQuote - i - 1));
if (endQuote === command.length - 1) { if (endQuote === command.length - 1) {
start = i = endQuote + 1; start = i = endQuote + 1;
@ -87,11 +88,11 @@ export function ParseCommand(command: string): (string | number | boolean)[] {
continue; continue;
} }
} else if (inQuote === ``) { } else if (inQuote === ``) {
inQuote = `'`; inQuote = KEY.QUOTE;
} else if (inQuote === `'`) { } else if (inQuote === KEY.QUOTE) {
inQuote = ``; inQuote = ``;
} }
} else if (c === " " && inQuote === ``) { } else if (c === KEY.SPACE && inQuote === ``) {
const arg = command.substr(start, i - start); const arg = command.substr(start, i - start);
// If this is a number, convert it from a string to number // If this is a number, convert it from a string to number

@ -20,7 +20,7 @@ function isNs2(filename: string): boolean {
return filename.endsWith(".ns") || filename.endsWith(".js"); return filename.endsWith(".ns") || filename.endsWith(".js");
} }
const newNs2Template = `/** @param {NS} ns **/ const newNs2Template = `/** @param {NS} ns */
export async function main(ns) { export async function main(ns) {
}`; }`;

@ -97,7 +97,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
break; break;
case "deletewordbefore": // Delete rest of word before the cursor case "deletewordbefore": // Delete rest of word before the cursor
for (let delStart = start - 1; delStart > -2; --delStart) { for (let delStart = start - 1; delStart > -2; --delStart) {
if ((inputText.charAt(delStart) === " " || delStart === -1) && delStart !== start - 1) { if ((inputText.charAt(delStart) === KEY.SPACE || delStart === -1) && delStart !== start - 1) {
saveValue(inputText.substr(0, delStart + 1) + inputText.substr(start), () => { saveValue(inputText.substr(0, delStart + 1) + inputText.substr(start), () => {
// Move cursor to correct location // Move cursor to correct location
// foo bar |baz bum --> foo |baz bum // foo bar |baz bum --> foo |baz bum
@ -110,7 +110,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
break; break;
case "deletewordafter": // Delete rest of word after the cursor, including trailing space case "deletewordafter": // Delete rest of word after the cursor, including trailing space
for (let delStart = start + 1; delStart <= value.length + 1; ++delStart) { for (let delStart = start + 1; delStart <= value.length + 1; ++delStart) {
if (inputText.charAt(delStart) === " " || delStart === value.length + 1) { if (inputText.charAt(delStart) === KEY.SPACE || delStart === value.length + 1) {
saveValue(inputText.substr(0, start) + inputText.substr(delStart + 1), () => { saveValue(inputText.substr(0, start) + inputText.substr(delStart + 1), () => {
// Move cursor to correct location // Move cursor to correct location
// foo bar |baz bum --> foo bar |bum // foo bar |baz bum --> foo bar |bum
@ -151,7 +151,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
break; break;
case "prevword": case "prevword":
for (let i = start - 2; i >= 0; --i) { for (let i = start - 2; i >= 0; --i) {
if (ref.value.charAt(i) === " ") { if (ref.value.charAt(i) === KEY.SPACE) {
ref.setSelectionRange(i + 1, i + 1); ref.setSelectionRange(i + 1, i + 1);
return; return;
} }
@ -163,7 +163,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
break; break;
case "nextword": case "nextword":
for (let i = start + 1; i <= inputLength; ++i) { for (let i = start + 1; i <= inputLength; ++i) {
if (ref.value.charAt(i) === " ") { if (ref.value.charAt(i) === KEY.SPACE) {
ref.setSelectionRange(i, i); ref.setSelectionRange(i, i);
return; return;
} }
@ -262,7 +262,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
} }
// Select previous command. // Select previous command.
if (event.key === KEY.UPARROW || (Settings.EnableBashHotkeys && event.key === "p" && event.ctrlKey)) { if (event.key === KEY.UP_ARROW || (Settings.EnableBashHotkeys && event.key === KEY.P && event.ctrlKey)) {
if (Settings.EnableBashHotkeys) { if (Settings.EnableBashHotkeys) {
event.preventDefault(); event.preventDefault();
} }
@ -290,7 +290,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
} }
// Select next command // Select next command
if (event.key === KEY.DOWNARROW || (Settings.EnableBashHotkeys && event.key === "m" && event.ctrlKey)) { if (event.key === KEY.DOWN_ARROW || (Settings.EnableBashHotkeys && event.key === KEY.M && event.ctrlKey)) {
if (Settings.EnableBashHotkeys) { if (Settings.EnableBashHotkeys) {
event.preventDefault(); event.preventDefault();
} }

@ -119,7 +119,7 @@ export const logBoxBaseZIndex = 1500;
function LogWindow(props: IProps): React.ReactElement { function LogWindow(props: IProps): React.ReactElement {
const draggableRef = useRef<HTMLDivElement>(null); const draggableRef = useRef<HTMLDivElement>(null);
const rootRef = useRef<Draggable>(null) const rootRef = useRef<Draggable>(null);
const [script, setScript] = useState(props.script); const [script, setScript] = useState(props.script);
const classes = useStyles(); const classes = useStyles();
const container = useRef<HTMLDivElement>(null); const container = useRef<HTMLDivElement>(null);
@ -129,22 +129,22 @@ function LogWindow(props: IProps): React.ReactElement {
setRerender((old) => !old); setRerender((old) => !old);
} }
useEffect( // useEffect(
() => // () =>
WorkerScriptStartStopEventEmitter.subscribe(() => { // WorkerScriptStartStopEventEmitter.subscribe(() => {
setTimeout(() => { // setTimeout(() => {
const server = GetServer(script.server); // const server = GetServer(script.server);
if (server === null) return; // if (server === null) return;
const exisitingScript = findRunningScript(script.filename, script.args, server); // const exisitingScript = findRunningScript(script.filename, script.args, server);
if (exisitingScript) { // if (exisitingScript) {
exisitingScript.logs = script.logs.concat(exisitingScript.logs) // exisitingScript.logs = script.logs.concat(exisitingScript.logs)
setScript(exisitingScript) // setScript(exisitingScript)
} // }
rerender(); // rerender();
}, 100) // }, 100)
}), // }),
[], // [],
); // );
useEffect(() => { useEffect(() => {
updateLayer(); updateLayer();
@ -224,11 +224,8 @@ function LogWindow(props: IProps): React.ReactElement {
const isOnScreen = (node: HTMLDivElement): boolean => { const isOnScreen = (node: HTMLDivElement): boolean => {
const bounds = node.getBoundingClientRect(); const bounds = node.getBoundingClientRect();
return !(bounds.right < 0 || return !(bounds.right < 0 || bounds.bottom < 0 || bounds.left > innerWidth || bounds.top > outerWidth);
bounds.bottom < 0 || };
bounds.left > innerWidth ||
bounds.top > outerWidth);
}
const resetPosition = (): void => { const resetPosition = (): void => {
const node = rootRef?.current; const node = rootRef?.current;
@ -237,14 +234,11 @@ function LogWindow(props: IProps): React.ReactElement {
state.x = 0; state.x = 0;
state.y = 0; state.y = 0;
node.setState(state); node.setState(state);
} };
const boundToBody = (e: any): void | false => { const boundToBody = (e: any): void | false => {
if (e.clientX < 0 || if (e.clientX < 0 || e.clientY < 0 || e.clientX > innerWidth || e.clientY > innerHeight) return false;
e.clientY < 0 || };
e.clientX > innerWidth ||
e.clientY > innerHeight) return false;
}
return ( return (
<Draggable handle=".drag" onDrag={boundToBody} ref={rootRef}> <Draggable handle=".drag" onDrag={boundToBody} ref={rootRef}>

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

@ -8,10 +8,29 @@ export enum KEY {
ENTER = "Enter", ENTER = "Enter",
ESC = "Escape", ESC = "Escape",
TAB = "Tab", TAB = "Tab",
UPARROW = "ArrowUp", SPACE = " ",
DOWNARROW = "ArrowDown", BACKSPACE = "Backspace",
LEFTARROW = "ArrowLeft", UP_ARROW = "ArrowUp",
RIGHTARROW = "ArrowRight", DOWN_ARROW = "ArrowDown",
LEFT_ARROW = "ArrowLeft",
RIGHT_ARROW = "ArrowRight",
QUOTE = "'",
DOUBLE_QUOTE = '"',
OPEN_BRACKET = "[",
CLOSE_BRACKET = "]",
LESS_THAN = "<",
GREATER_THAN = ">",
OPEN_PARENTHESIS = "(",
CLOSE_PARENTHESIS = ")",
OPEN_BRACE = "{",
CLOSE_BRACE = "}",
PIPE = "|",
DOT = ".",
FORWARD_SLASH = "/",
HYPHEN = "-",
HASH = "#",
k0 = "0", k0 = "0",
k1 = "1", k1 = "1",

@ -8,7 +8,7 @@ jest.mock(`!!raw-loader!../NetscriptDefinitions.d.ts`, () => "", {
virtual: true, virtual: true,
}); });
const code = `/** @param {NS} ns **/ const code = `/** @param {NS} ns */
export async function main(ns) { export async function main(ns) {
ns.print(ns.getWeakenTime('n00dles')); ns.print(ns.getWeakenTime('n00dles'));
}`; }`;