Merge pull request #4205 from Snarling/ramTestFix

TESTS: Refined ram calculation tests
This commit is contained in:
hydroflame 2022-10-09 00:23:04 -04:00 committed by GitHub
commit a5b2512269
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
153 changed files with 851 additions and 4069 deletions

@ -51,11 +51,9 @@ Here is a summary of all rules you need to follow when writing Netscript JS code
* grow
* weaken
* sleep
* asleep
* prompt
* wget
* scp
* write
* writePort
* Any function that contains :code:`await` must be declared as :code:`async`
@ -147,9 +145,7 @@ You may have noticed that every new ns2 file will contains the following comment
.. code-block:: javascript
/**
* @param {NS} ns
**/
/** @param {NS} ns */
This comment is used to help the text editor autocomplete functions in the Netscript API. You can enable it by pressing ctrl+space after `ns.`

@ -20,7 +20,6 @@ import { SpecialServers } from "../Server/data/SpecialServers";
import { Server } from "../Server/Server";
import { Router } from "../ui/GameRoot";
import { Page } from "../ui/Router";
import { IMap } from "../types";
import * as data from "./AchievementData.json";
import { FactionNames } from "../Faction/data/FactionNames";
import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames";
@ -47,7 +46,7 @@ export interface PlayerAchievement {
}
export interface AchievementDataJson {
achievements: IMap<AchievementData>;
achievements: Record<string, AchievementData>;
}
export interface AchievementData {
@ -87,7 +86,7 @@ function sfAchievement(): Achievement[] {
return achs;
}
export const achievements: IMap<Achievement> = {
export const achievements: Record<string, Achievement> = {
[FactionNames.CyberSec.toUpperCase()]: {
...achievementData[FactionNames.CyberSec.toUpperCase()],
Icon: "CSEC",

@ -1,8 +1,7 @@
import { IMap } from "./types";
import { Terminal } from "./Terminal";
export let Aliases: IMap<string> = {};
export let GlobalAliases: IMap<string> = {};
export let Aliases: Record<string, string> = {};
export let GlobalAliases: Record<string, string> = {};
export function loadAliases(saveString: string): void {
if (saveString === "") {

@ -1,4 +1,3 @@
import { Augmentation } from "./Augmentation";
import { IMap } from "../types";
export const StaticAugmentations: IMap<Augmentation> = {};
export const StaticAugmentations: Record<string, Augmentation> = {};

@ -1,6 +1,3 @@
/**
* React component for displaying the player's multipliers on the Augmentation UI page
*/
import { DoubleArrow } from "@mui/icons-material";
import { List, ListItem, ListItemText, Paper, Typography } from "@mui/material";
import * as React from "react";
@ -85,6 +82,7 @@ function MultiplierList(props: IMultiplierListProps): React.ReactElement {
return listItems.length > 0 ? <List disablePadding>{listItems}</List> : <></>;
}
/** React component for displaying the player's multipliers on the Augmentation UI page */
export function PlayerMultipliers(): React.ReactElement {
const mults = calculateAugmentedStats();

@ -1,7 +1,6 @@
import React from "react";
import { Player } from "../Player";
import { BitNodeMultipliers, IBitNodeMultipliers } from "./BitNodeMultipliers";
import { IMap } from "../types";
import { FactionNames } from "../Faction/data/FactionNames";
import { CityName } from "../Locations/data/CityNames";
@ -29,7 +28,7 @@ class BitNode {
}
}
export const BitNodes: IMap<BitNode> = {};
export const BitNodes: Record<string, BitNode> = {};
export function initBitNodes() {
BitNodes["BitNode1"] = new BitNode(
1,

@ -6,129 +6,79 @@ import { defaultMultipliers } from "./BitNode";
* player toward the intended strategy. Unless they really want to play the long, slow game of waiting...
*/
export interface IBitNodeMultipliers {
/**
* Influences how quickly the player's agility level (not exp) scales
*/
/** Influences how quickly the player's agility level (not exp) scales */
AgilityLevelMultiplier: number;
/**
* Influences the base cost to purchase an augmentation.
*/
/** Influences the base cost to purchase an augmentation. */
AugmentationMoneyCost: number;
/**
* Influences the base rep the player must have with a faction to purchase an augmentation.
*/
/** Influences the base rep the player must have with a faction to purchase an augmentation. */
AugmentationRepCost: number;
/**
* Influences how quickly the player can gain rank within Bladeburner.
*/
/** Influences how quickly the player can gain rank within Bladeburner. */
BladeburnerRank: number;
/**
* Influences the cost of skill levels from Bladeburner.
*/
/** Influences the cost of skill levels from Bladeburner. */
BladeburnerSkillCost: number;
/**
* Influences how quickly the player's charisma level (not exp) scales
*/
/** Influences how quickly the player's charisma level (not exp) scales */
CharismaLevelMultiplier: number;
/**
* Influences the experience gained for each ability when a player completes a class.
*/
/** Influences the experience gained for each ability when a player completes a class. */
ClassGymExpGain: number;
/**
* Influences the amount of money gained from completing Coding Contracts
**/
/**Influences the amount of money gained from completing Coding Contracts. */
CodingContractMoney: number;
/**
* Influences the experience gained for each ability when the player completes working their job.
*/
/** Influences the experience gained for each ability when the player completes working their job. */
CompanyWorkExpGain: number;
/**
* Influences how much money the player earns when completing working their job.
*/
/** Influences how much money the player earns when completing working their job. */
CompanyWorkMoney: number;
/**
* Influences the valuation of corporations created by the player.
*/
/** Influences the valuation of corporations created by the player. */
CorporationValuation: number;
/**
* Influences the base experience gained for each ability when the player commits a crime.
*/
/** Influences the base experience gained for each ability when the player commits a crime. */
CrimeExpGain: number;
/**
* Influences the base money gained when the player commits a crime.
*/
/** Influences the base money gained when the player commits a crime. */
CrimeMoney: number;
/**
* Influences how many Augmentations you need in order to get invited to the Daedalus faction
*/
/** Influences how many Augmentations you need in order to get invited to the Daedalus faction */
DaedalusAugsRequirement: number;
/**
* Influences how quickly the player's defense level (not exp) scales
*/
/** Influences how quickly the player's defense level (not exp) scales */
DefenseLevelMultiplier: number;
/**
* Influences how quickly the player's dexterity level (not exp) scales
*/
/** Influences how quickly the player's dexterity level (not exp) scales */
DexterityLevelMultiplier: number;
/**
* Influences how much rep the player gains in each faction simply by being a member.
*/
/** Influences how much rep the player gains in each faction simply by being a member. */
FactionPassiveRepGain: number;
/**
* Influences the experience gained for each ability when the player completes work for a Faction.
*/
/** Influences the experience gained for each ability when the player completes work for a Faction. */
FactionWorkExpGain: number;
/**
* Influences how much rep the player gains when performing work for a faction.
*/
/** Influences how much rep the player gains when performing work for a faction. */
FactionWorkRepGain: number;
/**
* Influences how much it costs to unlock the stock market's 4S Market Data API
*/
/** Influences how much it costs to unlock the stock market's 4S Market Data API */
FourSigmaMarketDataApiCost: number;
/**
* Influences how much it costs to unlock the stock market's 4S Market Data (NOT API)
*/
/** Influences how much it costs to unlock the stock market's 4S Market Data (NOT API) */
FourSigmaMarketDataCost: number;
/**
* Reduces gangs earning.
*/
/** Reduces gangs earning. */
GangSoftcap: number;
/**
* Percentage of unique augs that the gang has.
*/
/** 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. */
HackExpGain: number;
/**
* Influences how quickly the player's hacking level (not experience) scales
*/
/** Influences how quickly the player's hacking level (not experience) scales */
HackingLevelMultiplier: number;
/**
@ -137,19 +87,13 @@ export interface IBitNodeMultipliers {
*/
HacknetNodeMoney: number;
/**
* Influences how much money it costs to upgrade your home computer's RAM
*/
/** Influences how much money it costs to upgrade your home computer's RAM */
HomeComputerRamCost: number;
/**
* Influences how much money is gained when the player infiltrates a company.
*/
/** Influences how much money is gained when the player infiltrates a company. */
InfiltrationMoney: number;
/**
* Influences how much rep the player can gain from factions when selling stolen documents and secrets
*/
/** Influences how much rep the player can gain from factions when selling stolen documents and secrets */
InfiltrationRep: number;
/**
@ -158,33 +102,22 @@ export interface IBitNodeMultipliers {
*/
ManualHackMoney: number;
/**
* Influence how much it costs to purchase a server
*/
/** Influence how much it costs to purchase a server */
PurchasedServerCost: number;
/**
* Influence how much it costs to purchase a server
*/
/** Influence how much it costs to purchase a server */
PurchasedServerSoftcap: number;
/**
* Influences the maximum number of purchased servers you can have
*/
/** Influences the maximum number of purchased servers you can have */
PurchasedServerLimit: number;
/**
* Influences the maximum allowed RAM for a purchased server
*/
/** Influences the maximum allowed RAM for a purchased server */
PurchasedServerMaxRam: 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;
/**
* Influences how much money can be stolen from a server when a script performs a hack against it.
*/
/** Influences how much money can be stolen from a server when a script performs a hack against it. */
ScriptHackMoney: number;
/**
@ -194,62 +127,40 @@ export interface IBitNodeMultipliers {
*/
ScriptHackMoneyGain: number;
/**
* Influences the growth percentage per cycle against a server.
*/
/** Influences the growth percentage per cycle against a server. */
ServerGrowthRate: number;
/**
* Influences the maxmimum money that a server can grow to.
*/
/** Influences the maxmimum money that a server can grow to. */
ServerMaxMoney: number;
/**
* Influences the initial money that a server starts with.
*/
/** Influences the initial money that a server starts with. */
ServerStartingMoney: number;
/**
* Influences the initial security level (hackDifficulty) of a server.
*/
/** Influences the initial security level (hackDifficulty) of a server. */
ServerStartingSecurity: number;
/**
* Influences the weaken amount per invocation against a server.
*/
/** Influences the weaken amount per invocation against a server. */
ServerWeakenRate: number;
/**
* Influences how quickly the player's strength level (not exp) scales
*/
/** Influences how quickly the player's strength level (not exp) scales */
StrengthLevelMultiplier: number;
/**
* Influences the power of the gift.
*/
/** Influences the power of the gift. */
StaneksGiftPowerMultiplier: number;
/**
* Influences the size of the gift.
*/
/** Influences the size of the gift. */
StaneksGiftExtraSize: number;
/**
* Influences the hacking skill required to backdoor the world daemon.
*/
/** Influences the hacking skill required to backdoor the world daemon. */
WorldDaemonDifficulty: number;
/**
* Influences corporation dividends.
*/
/** Influences corporation dividends. */
CorporationSoftcap: number;
// Index signature
[key: string]: number;
}
/**
* The multipliers that are influenced by current Bitnode progression.
*/
/** The multipliers that are influenced by current Bitnode progression. */
// tslint:disable-next-line:variable-name
export const BitNodeMultipliers = Object.assign({}, defaultMultipliers);

@ -1,8 +1,7 @@
import { BlackOperation } from "./BlackOperation";
import { IMap } from "../types";
import { BlackOperationNames } from "./data/BlackOperationNames";
export const BlackOperations: IMap<BlackOperation> = {};
export const BlackOperations: Record<string, BlackOperation> = {};
(function () {
BlackOperations[BlackOperationNames.OperationTyphoon] = new BlackOperation({

@ -2377,16 +2377,12 @@ export class Bladeburner {
}
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("Bladeburner", this);
}
/**
* Initiatizes a Bladeburner object from a JSON save state.
*/
/** Initiatizes a Bladeburner object from a JSON save state. */
static fromJSON(value: IReviverValue): Bladeburner {
return Generic_fromJSON(Bladeburner, value.data);
}

@ -4,7 +4,9 @@ import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../uti
import { addOffset } from "../utils/helpers/addOffset";
interface IChangePopulationByCountParams {
/** How much the estimate should change by. */
estChange: number;
/** Add offset to estimate (offset by percentage). */
estOffset: number;
}
@ -14,29 +16,19 @@ interface IChangePopulationByPercentageParams {
}
export class City {
/**
* Name of the city.
*/
/** Name of the city. */
name = "";
/**
* Population of the city.
*/
/** Population of the city. */
pop = 0;
/**
* Population estimation of the city.
*/
/** Population estimation of the city. */
popEst = 0;
/**
* Number of communities in the city.
*/
/** Number of communities in the city. */
comms = 0;
/**
* Chaos level of the city.
*/
/** Chaos level of the city. */
chaos = 0;
constructor(name: string = BladeburnerConstants.CityNames[2]) {
@ -51,9 +43,7 @@ export class City {
this.chaos = 0;
}
/**
* p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%)
*/
/** p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%) */
changeChaosByPercentage(p: number): void {
if (isNaN(p)) {
throw new Error("NaN passed into City.chaosChaosByPercentage()");
@ -84,9 +74,7 @@ export class City {
}
}
/**
* p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%)
*/
/** p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%) */
improvePopulationEstimateByPercentage(p: number, skillMult = 1): void {
p = p * skillMult;
if (isNaN(p)) {
@ -106,11 +94,6 @@ export class City {
}
}
/**
* @params options:
* estChange(int): How much the estimate should change by
* estOffset(int): Add offset to estimate (offset by percentage)
*/
changePopulationByCount(n: number, params: IChangePopulationByCountParams = { estChange: 0, estOffset: 0 }): void {
if (isNaN(n)) {
throw new Error("NaN passed into City.changePopulationByCount()");
@ -174,16 +157,12 @@ export class City {
}
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("City", this);
}
/**
* Initiatizes a City object from a JSON save state.
*/
/** Initiatizes a City object from a JSON save state. */
static fromJSON(value: IReviverValue): City {
return Generic_fromJSON(City, value.data);
}

@ -1,7 +1,6 @@
import { Action } from "./Action";
import { IMap } from "../types";
export const GeneralActions: IMap<Action> = {};
export const GeneralActions: Record<string, Action> = {};
const actionNames: Array<string> = [
"Training",

@ -1,8 +1,7 @@
import { Skill } from "./Skill";
import { SkillNames } from "./data/SkillNames";
import { IMap } from "../types";
export const Skills: IMap<Skill> = {};
export const Skills: Record<string, Skill> = {};
(function () {
Skills[SkillNames.BladesIntuition] = new Skill({

@ -55,7 +55,7 @@ export function generateContract(params: IGenerateContractParams): void {
// Problem Type
let problemType;
const problemTypes = Object.keys(CodingContractTypes);
if (params.problemType != null && problemTypes.includes(params.problemType)) {
if (params.problemType && problemTypes.includes(params.problemType)) {
problemType = params.problemType;
} else {
problemType = getRandomProblemType();

@ -1,7 +1,5 @@
import { codingContractTypesMetadata, DescriptionFunc, GeneratorFunc, SolverFunc } from "./data/codingcontracttypes";
import { IMap } from "./types";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "./utils/JSONReviver";
import { CodingContractEvent } from "./ui/React/CodingContractModal";
@ -9,34 +7,22 @@ import { CodingContractEvent } from "./ui/React/CodingContractModal";
/* Represents different types of problems that a Coding Contract can have */
class CodingContractType {
/**
* Function that generates a description of the problem
*/
/** Function that generates a description of the problem */
desc: DescriptionFunc;
/**
* Number that generally represents the problem's difficulty. Bigger numbers = harder
*/
/** Number that generally represents the problem's difficulty. Bigger numbers = harder */
difficulty: number;
/**
* A function that randomly generates a valid 'data' for the problem
*/
/** A function that randomly generates a valid 'data' for the problem */
generate: GeneratorFunc;
/**
* Name of the type of problem
*/
/** Name of the type of problem */
name: string;
/**
* The maximum number of tries the player gets on this kind of problem before it self-destructs
*/
/** The maximum number of tries the player gets on this kind of problem before it self-destructs */
numTries: number;
/**
* Stores a function that checks if the provided answer is correct
*/
/** Stores a function that checks if the provided answer is correct */
solver: SolverFunc;
constructor(
@ -58,7 +44,7 @@ class CodingContractType {
/* Contract Types */
// tslint:disable-next-line
export const CodingContractTypes: IMap<CodingContractType> = {};
export const CodingContractTypes: Record<string, CodingContractType> = {};
for (const md of codingContractTypesMetadata) {
// tslint:disable-next-line
@ -72,9 +58,7 @@ for (const md of codingContractTypesMetadata) {
);
}
/**
* Enum representing the different types of rewards a Coding Contract can give
*/
/** Enum representing the different types of rewards a Coding Contract can give */
export enum CodingContractRewardType {
FactionReputation,
FactionReputationAll,
@ -82,18 +66,14 @@ export enum CodingContractRewardType {
Money, // This must always be the last reward type
}
/**
* Enum representing the result when trying to solve the Contract
*/
/** Enum representing the result when trying to solve the Contract */
export enum CodingContractResult {
Success,
Failure,
Cancelled,
}
/**
* A class that represents the type of reward a contract gives
*/
/** A class that represents the type of reward a contract gives */
export interface ICodingContractReward {
/* Name of Company/Faction name for reward, if applicable */
name?: string;
@ -161,9 +141,7 @@ export class CodingContract {
return CodingContractTypes[this.type].solver(this.data, solution);
}
/**
* Creates a popup to prompt the player to solve the problem
*/
/** Creates a popup to prompt the player to solve the problem */
async prompt(): Promise<CodingContractResult> {
return new Promise<CodingContractResult>((resolve) => {
const props = {
@ -183,16 +161,12 @@ export class CodingContract {
});
}
/**
* Serialize the current file to a JSON save state.
*/
/** Serialize the current file to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("CodingContract", this);
}
/**
* Initiatizes a CodingContract from a JSON save state.
*/
/** Initiatizes a CodingContract from a JSON save state. */
static fromJSON(value: IReviverValue): CodingContract {
return Generic_fromJSON(CodingContract, value.data);
}

@ -1,10 +1,9 @@
// Constructs all CompanyPosition objects using the metadata in data/companypositions.ts
import { companiesMetadata } from "./data/CompaniesMetadata";
import { Company, IConstructorParams } from "./Company";
import { IMap } from "../types";
import { Reviver } from "../utils/JSONReviver";
export let Companies: IMap<Company> = {};
export let Companies: Record<string, Company> = {};
function addCompany(params: IConstructorParams): void {
if (Companies[params.name] != null) {

@ -2,14 +2,12 @@ import { CompanyPosition } from "./CompanyPosition";
import * as posNames from "./data/companypositionnames";
import { favorToRep, repToFavor } from "../Faction/formulas/favor";
import { IMap } from "../types";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
export interface IConstructorParams {
name: string;
info: string;
companyPositions: IMap<boolean>;
companyPositions: Record<string, boolean>;
expMultiplier: number;
salaryMultiplier: number;
jobStatReqOffset: number;
@ -26,19 +24,13 @@ const DefaultConstructorParams: IConstructorParams = {
};
export class Company {
/**
* Company name
*/
/** Company name */
name: string;
/**
* Description and general information about company
*/
/** Description and general information about company */
info: string;
/**
* Has faction associated.
*/
/** Has faction associated. */
isMegacorp: boolean;
/**
@ -48,11 +40,9 @@ export class Company {
*
* Must match names of Company Positions, defined in data/companypositionnames.ts
*/
companyPositions: IMap<boolean>;
companyPositions: Record<string, boolean>;
/**
* Company-specific multiplier for earnings
*/
/** Company-specific multiplier for earnings */
expMultiplier: number;
salaryMultiplier: number;
@ -65,9 +55,7 @@ export class Company {
*/
jobStatReqOffset: number;
/**
* Properties to track the player's progress in this company
*/
/** Properties to track the player's progress in this company */
isPlayerEmployed: boolean;
playerReputation: number;
favor: number;
@ -144,16 +132,12 @@ export class Company {
return newFavor - this.favor;
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("Company", this);
}
/**
* Initiatizes a Company from a JSON save state.
*/
/** Initiatizes a Company from a JSON save state. */
static fromJSON(value: IReviverValue): Company {
return Generic_fromJSON(Company, value.data);
}

@ -33,14 +33,10 @@ export interface IConstructorParams {
}
export class CompanyPosition {
/**
* Position title
*/
/** Position title */
name: string;
/**
* Title of next position to be promoted to
*/
/** Title of next position to be promoted to */
nextPosition: string | null;
/**
@ -49,14 +45,10 @@ export class CompanyPosition {
*/
baseSalary: number;
/**
* Reputation multiplier
*/
/** Reputation multiplier */
repMultiplier: number;
/**
* Required stats to earn this position
*/
/** Required stats to earn this position */
requiredAgility: number;
requiredCharisma: number;
requiredDefense: number;
@ -64,14 +56,10 @@ export class CompanyPosition {
requiredHacking: number;
requiredStrength: number;
/**
* Required company reputation to earn this position
*/
/** Required company reputation to earn this position */
requiredReputation: number;
/**
* Effectiveness of each stat time for job performance
*/
/** Effectiveness of each stat time for job performance */
hackingEffectiveness: number;
strengthEffectiveness: number;
defenseEffectiveness: number;
@ -79,9 +67,7 @@ export class CompanyPosition {
agilityEffectiveness: number;
charismaEffectiveness: number;
/**
* Experience gain for performing job (per 200ms game cycle)
*/
/** Experience gain for performing job (per 200ms game cycle) */
hackingExpGain: number;
strengthExpGain: number;
defenseExpGain: number;

@ -1,9 +1,8 @@
// Constructs all CompanyPosition objects using the metadata in data/companypositions.ts
import { companyPositionMetadata } from "./data/CompanyPositionsMetadata";
import { CompanyPosition, IConstructorParams } from "./CompanyPosition";
import { IMap } from "../types";
export const CompanyPositions: IMap<CompanyPosition> = {};
export const CompanyPositions: Record<string, CompanyPosition> = {};
function addCompanyPosition(params: IConstructorParams): void {
if (CompanyPositions[params.name] != null) {

@ -1,10 +1,7 @@
import { Company } from "./Company";
import { CompanyPosition } from "./CompanyPosition";
/**
* Returns a string with the given CompanyPosition's stat requirements
*/
/** Returns a string with the given CompanyPosition's stat requirements */
export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext = false): string {
let reqText = "";
const offset: number = company.jobStatReqOffset;

@ -1,30 +1,29 @@
import * as posNames from "./companypositionnames";
import { IConstructorParams } from "../Company";
import { IMap } from "../../types";
import { LocationName } from "../../Locations/data/LocationNames";
// Create Objects containing Company Positions by category
// Will help in metadata construction later
const AllSoftwarePositions: IMap<boolean> = {};
const AllITPositions: IMap<boolean> = {};
const AllNetworkEngineerPositions: IMap<boolean> = {};
const SecurityEngineerPositions: IMap<boolean> = {};
const AllTechnologyPositions: IMap<boolean> = {};
const AllBusinessPositions: IMap<boolean> = {};
const AllAgentPositions: IMap<boolean> = {};
const AllSecurityPositions: IMap<boolean> = {};
const AllSoftwareConsultantPositions: IMap<boolean> = {};
const AllBusinessConsultantPositions: IMap<boolean> = {};
const SoftwarePositionsUpToHeadOfEngineering: IMap<boolean> = {};
const SoftwarePositionsUpToLeadDeveloper: IMap<boolean> = {};
const BusinessPositionsUpToOperationsManager: IMap<boolean> = {};
const WaiterOnly: IMap<boolean> = {};
const EmployeeOnly: IMap<boolean> = {};
const PartTimeWaiterOnly: IMap<boolean> = {};
const PartTimeEmployeeOnly: IMap<boolean> = {};
const OperationsManagerOnly: IMap<boolean> = {};
const CEOOnly: IMap<boolean> = {};
const AllSoftwarePositions: Record<string, boolean> = {};
const AllITPositions: Record<string, boolean> = {};
const AllNetworkEngineerPositions: Record<string, boolean> = {};
const SecurityEngineerPositions: Record<string, boolean> = {};
const AllTechnologyPositions: Record<string, boolean> = {};
const AllBusinessPositions: Record<string, boolean> = {};
const AllAgentPositions: Record<string, boolean> = {};
const AllSecurityPositions: Record<string, boolean> = {};
const AllSoftwareConsultantPositions: Record<string, boolean> = {};
const AllBusinessConsultantPositions: Record<string, boolean> = {};
const SoftwarePositionsUpToHeadOfEngineering: Record<string, boolean> = {};
const SoftwarePositionsUpToLeadDeveloper: Record<string, boolean> = {};
const BusinessPositionsUpToOperationsManager: Record<string, boolean> = {};
const WaiterOnly: Record<string, boolean> = {};
const EmployeeOnly: Record<string, boolean> = {};
const PartTimeWaiterOnly: Record<string, boolean> = {};
const PartTimeEmployeeOnly: Record<string, boolean> = {};
const OperationsManagerOnly: Record<string, boolean> = {};
const CEOOnly: Record<string, boolean> = {};
posNames.SoftwareCompanyPositions.forEach((e) => {
AllSoftwarePositions[e] = true;

@ -14,6 +14,7 @@ import { Cities } from "../Locations/Cities";
import { EmployeePositions } from "./EmployeePositions";
import { ResearchMap } from "./ResearchMap";
import { isRelevantMaterial } from "./ui/Helpers";
import { checkEnum } from "../utils/helpers/checkEnum";
export function NewIndustry(corporation: Corporation, industry: string, name: string): void {
if (corporation.divisions.find(({ type }) => industry == type))
@ -303,16 +304,13 @@ export function BuyBackShares(corporation: Corporation, numShares: number): bool
export function AssignJob(office: OfficeSpace, employeeName: string, job: string): void {
const employee = office.employees.find((e) => e.name === employeeName);
if (!employee) throw new Error(`Could not find employee '${name}'.`);
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`);
office.assignSingleJob(employee, job);
}
export function AutoAssignJob(office: OfficeSpace, job: string, count: number): boolean {
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`);
return office.autoAssignJob(job, count);
}

@ -446,16 +446,12 @@ export class Corporation {
return;
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("Corporation", this);
}
/**
* Initiatizes a Corporation object from a JSON save state.
*/
/** Initiatizes a Corporation object from a JSON save state. */
static fromJSON(value: IReviverValue): Corporation {
return Generic_fromJSON(Corporation, value.data);
}

@ -1,11 +1,9 @@
import { IMap } from "../types";
export const EmployeePositions: IMap<string> = {
Operations: "Operations",
Engineer: "Engineer",
Business: "Business",
Management: "Management",
RandD: "Research & Development",
Training: "Training",
Unassigned: "Unassigned",
};
export enum EmployeePositions {
Operations = "Operations",
Engineer = "Engineer",
Business = "Business",
Management = "Management",
RandD = "Research & Development",
Training = "Training",
Unassigned = "Unassigned",
}

@ -602,6 +602,7 @@ export class Industry {
}
}
// TODO: Change all these Object.keys where the value is also needed to Object.entries.
// Use the materials already in the warehouse if the option is on.
for (const matName of Object.keys(smartBuy)) {
if (!warehouse.smartSupplyUseLeftovers[matName]) continue;
@ -612,9 +613,8 @@ export class Industry {
}
// buy them
for (const matName of Object.keys(smartBuy)) {
for (const [matName, buyAmt] of Object.entries(smartBuy)) {
const mat = warehouse.materials[matName];
const buyAmt = smartBuy[matName];
if (buyAmt === undefined) throw new Error(`Somehow smartbuy matname is undefined`);
mat.qty += buyAmt;
expenses += buyAmt * mat.bCost;
@ -1369,16 +1369,12 @@ export class Industry {
return researchTree.getStorageMultiplier();
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("Industry", this);
}
/**
* Initiatizes a Industry object from a JSON save state.
*/
/** Initiatizes a Industry object from a JSON save state. */
static fromJSON(value: IReviverValue): Industry {
return Generic_fromJSON(Industry, value.data);
}

@ -1,7 +1,5 @@
import { IMap } from "../types";
// Map of material (by name) to their sizes (how much space it takes in warehouse)
export const MaterialSizes: IMap<number> = {
export const MaterialSizes: Record<string, number> = {
Water: 0.05,
Energy: 0.01,
Food: 0.03,

@ -4,7 +4,6 @@ import { Industry } from "./Industry";
import { ProductRatingWeights, IProductRatingWeight } from "./ProductRatingWeights";
import { createCityMap } from "../Locations/createCityMap";
import { IMap } from "../types";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
import { getRandomInt } from "../utils/helpers/getRandomInt";
@ -25,7 +24,7 @@ interface IConstructorParams {
features?: number;
loc?: string;
size?: number;
req?: IMap<number>;
req?: Record<string, number>;
}
export class Product {
@ -81,7 +80,7 @@ export class Product {
// Data refers to the production, sale, and quantity of the products
// These values are specific to a city
// For each city, the data is [qty, prod, sell]
data: IMap<number[]> = createCityMap<number[]>([0, 0, 0]);
data: Record<string, number[]> = createCityMap<number[]>([0, 0, 0]);
// Location of this Product
// Only applies for location-based products like restaurants/hospitals
@ -93,18 +92,18 @@ export class Product {
// Material requirements. An object that maps the name of a material to how much it requires
// to make 1 unit of the product.
reqMats: IMap<number> = {};
reqMats: Record<string, number> = {};
// Data to keep track of whether production/sale of this Product is
// manually limited. These values are specific to a city
// [Whether production/sale is limited, limit amount]
prdman: IMap<any[]> = createCityMap<any[]>([false, 0]);
sllman: IMap<any[]> = createCityMap<any[]>([false, 0]);
prdman: Record<string, any[]> = createCityMap<any[]>([false, 0]);
sllman: Record<string, any[]> = createCityMap<any[]>([false, 0]);
// Flags that signal whether automatic sale pricing through Market TA is enabled
marketTa1 = false;
marketTa2 = false;
marketTa2Price: IMap<number> = createCityMap<number>(0);
marketTa2Price: Record<string, number> = createCityMap<number>(0);
// Determines the maximum amount of this product that can be sold in one market cycle
maxsll = 0;

@ -1,5 +1,4 @@
import { Industries } from "./IndustryData";
import { IMap } from "../types";
export interface IProductRatingWeight {
Aesthetics?: number;
@ -10,7 +9,7 @@ export interface IProductRatingWeight {
Reliability?: number;
}
export const ProductRatingWeights: IMap<any> = {
export const ProductRatingWeights: Record<string, IProductRatingWeight> = {
[Industries.Food]: {
Quality: 0.7,
Durability: 0.1,

@ -2,9 +2,8 @@
// as values. They are identified by their names
import { Research, IConstructorParams } from "./Research";
import { researchMetadata } from "./data/ResearchMetadata";
import { IMap } from "../types";
export const ResearchMap: IMap<Research> = {};
export const ResearchMap: Record<string, Research> = {};
function addResearch(p: IConstructorParams): void {
if (ResearchMap[p.name] != null) {

@ -6,8 +6,6 @@
import { Research } from "./Research";
import { ResearchMap } from "./ResearchMap";
import { IMap } from "../types";
interface IConstructorParams {
children?: Node[];
cost: number;
@ -86,7 +84,7 @@ export class Node {
// The root node in a Research Tree must always be the "Hi-Tech R&D Laboratory"
export class ResearchTree {
// Object containing names of all acquired Research by name
researched: IMap<boolean> = {};
researched: Record<string, boolean> = {};
// Root Node
root: Node | null = null;

@ -2,7 +2,6 @@ import { Material } from "./Material";
import { Corporation } from "./Corporation";
import { Industry } from "./Industry";
import { MaterialSizes } from "./MaterialSizes";
import { IMap } from "../types";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
@ -21,7 +20,7 @@ export class Warehouse {
loc: string;
// Map of Materials held by this Warehouse
materials: IMap<Material>;
materials: Record<string, Material>;
// Maximum amount warehouse can hold
size: number;

@ -71,16 +71,12 @@ export class ActiveFragment {
return Object.assign({}, this);
}
/**
* Serialize an active fragment to a JSON save state.
*/
/** Serialize an active fragment to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("ActiveFragment", this);
}
/**
* Initializes an acive fragment from a JSON save state
*/
/** Initializes an acive fragment from a JSON save state */
static fromJSON(value: IReviverValue): ActiveFragment {
return Generic_fromJSON(ActiveFragment, value.data);
}

@ -230,16 +230,12 @@ export class StaneksGift extends BaseGift {
this.storedCycles = 0;
}
/**
* Serialize Staneks Gift to a JSON save state.
*/
/** Serialize Staneks Gift to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("StaneksGift", this);
}
/**
* Initializes Staneks Gift from a JSON save state
*/
/** Initializes Staneks Gift from a JSON save state */
static fromJSON(value: IReviverValue): StaneksGift {
return Generic_fromJSON(StaneksGift, value.data);
}

@ -1,11 +1,10 @@
import { Crime } from "./Crime";
import { CONSTANTS } from "../Constants";
import { IMap } from "../types";
import { CrimeType } from "../utils/WorkType";
export const Crimes: IMap<Crime> = {
export const Crimes: Record<string, Crime> = {
Shoplift: new Crime("Shoplift", "to shoplift", CrimeType.SHOPLIFT, 2e3, 15e3, 1 / 20, 0.1, {
dexterity_success_weight: 1,
agility_success_weight: 1,

@ -1,8 +1,7 @@
import { DarkWebItem } from "./DarkWebItem";
import { IMap } from "../types";
import { Programs, initPrograms } from "../Programs/Programs";
export const DarkWebItems: IMap<DarkWebItem> = {};
export const DarkWebItems: Record<string, DarkWebItem> = {};
export function initDarkWebItems() {
initPrograms();
Object.assign(DarkWebItems, {

@ -3,7 +3,7 @@ import { Router } from "./ui/GameRoot";
import { removeLeadingSlash } from "./Terminal/DirectoryHelpers";
import { Terminal } from "./Terminal";
import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar";
import { IMap, IReturnStatus } from "./types";
import { IReturnStatus } from "./types";
import { GetServer } from "./Server/AllServers";
import { ImportPlayerData, SaveData, saveObject } from "./SaveObject";
import { Settings } from "./Settings/Settings";
@ -125,7 +125,7 @@ function initWebserver(): void {
function initAppNotifier(): void {
const funcs = {
terminal: (message: string, type?: string) => {
const typesFn: IMap<(s: string) => void> = {
const typesFn: Record<string, (s: string) => void> = {
info: Terminal.info,
warn: Terminal.warn,
error: Terminal.error,

@ -9,34 +9,22 @@ export class Faction {
*/
alreadyInvited = false;
/**
* Holds names of all augmentations that this Faction offers
*/
/** Holds names of all augmentations that this Faction offers */
augmentations: string[] = [];
/**
* Amount of favor the player has with this faction.
*/
/** Amount of favor the player has with this faction. */
favor = 0;
/**
* Flag signalling whether player has been banned from this faction
*/
/** Flag signalling whether player has been banned from this faction */
isBanned = false;
/**
* Flag signalling whether player is a member of this faction
*/
/** Flag signalling whether player is a member of this faction */
isMember = false;
/**
* Name of faction
*/
/** Name of faction */
name = "";
/**
* Amount of reputation player has with this faction
*/
/** Amount of reputation player has with this faction */
playerReputation = 0;
constructor(name = "") {
@ -72,16 +60,12 @@ export class Faction {
return newFavor - this.favor;
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("Faction", this);
}
/**
* Initiatizes a Faction object from a JSON save state.
*/
/** Initiatizes a Faction object from a JSON save state. */
static fromJSON(value: IReviverValue): Faction {
return Generic_fromJSON(Faction, value.data);
}

@ -1,5 +1,4 @@
import React from "react";
import { IMap } from "../types";
import { FactionNames } from "./data/FactionNames";
import { Router } from "../ui/GameRoot";
import { Option } from "./ui/Option";
@ -16,48 +15,30 @@ interface FactionInfoParams {
assignment?: () => React.ReactElement;
}
/**
* Contains the "information" property for all the Factions, which is just a description of each faction
*/
/** Contains the "information" property for all the Factions, which is just a description of each faction */
export class FactionInfo {
/**
* The names of all other factions considered to be enemies to this faction.
*/
/** The names of all other factions considered to be enemies to this faction. */
enemies: string[];
/**
* The descriptive text to show on the faction's page.
*/
/** The descriptive text to show on the faction's page. */
infoText: JSX.Element;
/**
* A flag indicating if the faction supports field work to earn reputation.
*/
/** A flag indicating if the faction supports field work to earn reputation. */
offerFieldWork: boolean;
/**
* A flag indicating if the faction supports hacking work to earn reputation.
*/
/** A flag indicating if the faction supports hacking work to earn reputation. */
offerHackingWork: boolean;
/**
* A flag indicating if the faction supports security work to earn reputation.
*/
/** A flag indicating if the faction supports security work to earn reputation. */
offerSecurityWork: boolean;
/**
* Keep faction on install.
*/
/** Keep faction on install. */
keep: boolean;
/**
* Special faction
*/
/** Special faction */
special: boolean;
/**
* The data to display on the faction screen.
*/
/** The data to display on the faction screen. */
assignment?: () => React.ReactElement;
constructor(params: FactionInfoParams) {
@ -77,11 +58,9 @@ export class FactionInfo {
}
}
/**
* A map of all factions and associated info to them.
*/
/** A map of all factions and associated info to them. */
// tslint:disable-next-line:variable-name
export const FactionInfos: IMap<FactionInfo> = {
export const FactionInfos: Record<string, FactionInfo> = {
// Endgame
[FactionNames.Illuminati]: new FactionInfo({
infoText: (

@ -5,11 +5,9 @@
import { Faction } from "./Faction";
import { FactionInfos } from "./FactionInfo";
import { IMap } from "../types";
import { Reviver } from "../utils/JSONReviver";
export let Factions: IMap<Faction> = {};
export let Factions: Record<string, Faction> = {};
export function loadFactions(saveString: string): void {
Factions = JSON.parse(saveString, Reviver);

@ -1,6 +1,3 @@
/**
* Root React Component for displaying a faction's "Purchase Augmentations" page
*/
import { Box, Button, Tooltip, Typography, Paper, Container } from "@mui/material";
import React, { useState } from "react";
@ -23,6 +20,7 @@ type IProps = {
routeToMainPage: () => void;
};
/** Root React Component for displaying a faction's "Purchase Augmentations" page */
export function AugmentationsPage(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];

@ -1,6 +1,3 @@
/**
* React Component for the popup used to create a new gang.
*/
import React from "react";
import { Modal } from "../../ui/React/Modal";
import { Router } from "../../ui/GameRoot";
@ -16,6 +13,7 @@ interface IProps {
facName: string;
}
/** React Component for the popup used to create a new gang. */
export function CreateGangModal(props: IProps): React.ReactElement {
const combatGangText =
"This is a COMBAT gang. Members in this gang will have different tasks than HACKING gangs. " +

@ -1,6 +1,3 @@
/**
* React component for a donate option on the Faction UI
*/
import React, { useState } from "react";
import { CONSTANTS } from "../../Constants";
@ -27,6 +24,7 @@ type IProps = {
rerender: () => void;
};
/** React component for a donate option on the Faction UI */
export function DonateOption(props: IProps): React.ReactElement {
const [donateAmt, setDonateAmt] = useState<number>(NaN);
const digits = (CONSTANTS.DonateMoneyToRepDivisor + "").length - 1;

@ -376,7 +376,7 @@ export class Gang {
return Math.max(1, discount);
}
// Returns only valid tasks for this gang. Excludes 'Unassigned'
/** Returns only valid tasks for this gang. Excludes 'Unassigned' */
getAllTaskNames(): string[] {
return Object.keys(GangMemberTasks).filter((taskName: string) => {
const task = GangMemberTasks[taskName];
@ -394,16 +394,12 @@ export class Gang {
return upg.cost / this.getDiscount();
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("Gang", this);
}
/**
* Initiatizes a Gang object from a JSON save state.
*/
/** Initiatizes a Gang object from a JSON save state. */
static fromJSON(value: IReviverValue): Gang {
return Generic_fromJSON(Gang, value.data);
}

@ -319,16 +319,12 @@ export class GangMember {
return true;
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("GangMember", this);
}
/**
* Initiatizes a GangMember object from a JSON save state.
*/
/** Initiatizes a GangMember object from a JSON save state. */
static fromJSON(value: IReviverValue): GangMember {
return Generic_fromJSON(GangMember, value.data);
}

@ -6,24 +6,16 @@ import { ITaskParams } from "../ITaskParams";
* (defined in Gang.js)
*/
interface IGangMemberTaskMetadata {
/**
* Description of the task
*/
/** Description of the task */
desc: string;
/**
* Whether or not this task is meant for Combat-type gangs
*/
/** Whether or not this task is meant for Combat-type gangs */
isCombat: boolean;
/**
* Whether or not this task is for Hacking-type gangs
*/
/** Whether or not this task is for Hacking-type gangs */
isHacking: boolean;
/**
* Name of the task
*/
/** Name of the task */
name: string;
/**

@ -1,6 +1,3 @@
/**
* React Component for displaying the bonus time remaining.
*/
import * as React from "react";
import { Gang } from "../Gang";
import { CONSTANTS } from "../../Constants";
@ -13,6 +10,7 @@ interface IProps {
gang: Gang;
}
/** React Component for displaying the bonus time remaining. */
export function BonusTime(props: IProps): React.ReactElement {
const CyclerPerSecond = 1000 / CONSTANTS._idleSpeed;
if ((props.gang.storedCycles / CyclerPerSecond) * 1000 <= 5000) return <></>;

@ -1,6 +1,3 @@
/**
* React Component for the popup that manages gang members upgrades
*/
import React, { useState } from "react";
import { useGang } from "./Context";
@ -244,6 +241,7 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
);
}
/** React Component for the popup that manages gang members upgrades */
export function EquipmentsSubpage(): React.ReactElement {
const gang = useGang();
const [filter, setFilter] = useState("");

@ -1,6 +1,3 @@
/**
* React Component for a gang member on the management subpage.
*/
import React from "react";
import { GangMember } from "../GangMember";
import { GangMemberCardContent } from "./GangMemberCardContent";
@ -14,6 +11,7 @@ interface IProps {
member: GangMember;
}
/** React Component for a gang member on the management subpage. */
export function GangMemberCard(props: IProps): React.ReactElement {
return (
<Box component={Paper} sx={{ width: "auto" }}>

@ -1,6 +1,3 @@
/**
* React Component for the list of gang members on the management subpage.
*/
import React, { useState } from "react";
import { GangMemberCard } from "./GangMemberCard";
import { RecruitButton } from "./RecruitButton";
@ -12,6 +9,7 @@ import SearchIcon from "@mui/icons-material/Search";
import { GangMember } from "../GangMember";
import { OptionSwitch } from "../../ui/React/OptionSwitch";
/** React Component for the list of gang members on the management subpage. */
export function GangMemberList(): React.ReactElement {
const gang = useGang();
const setRerender = useState(false)[1];

@ -1,6 +1,3 @@
/**
* React Component for all the gang stuff.
*/
import React, { useState, useEffect } from "react";
import { ManagementSubpage } from "./ManagementSubpage";
import { TerritorySubpage } from "./TerritorySubpage";
@ -11,6 +8,7 @@ import { Context } from "./Context";
import Tabs from "@mui/material/Tabs";
import Tab from "@mui/material/Tab";
/** React Component for all the gang stuff. */
export function GangRoot(): React.ReactElement {
const gang = (function () {
if (Player.gang === null) throw new Error("Gang should not be null");

@ -1,12 +1,10 @@
/**
* React Component for the subpage that manages gang members, the main page.
*/
import React from "react";
import { GangStats } from "./GangStats";
import { GangMemberList } from "./GangMemberList";
import { useGang } from "./Context";
import Typography from "@mui/material/Typography";
/** React Component for the subpage that manages gang members, the main page. */
export function ManagementSubpage(): React.ReactElement {
const gang = useGang();
return (

@ -1,6 +1,3 @@
/**
* React Component for the recruitment button and text on the gang main page.
*/
import React, { useState } from "react";
import { RecruitModal } from "./RecruitModal";
import { GangConstants } from "../data/Constants";
@ -14,6 +11,7 @@ interface IProps {
onRecruit: () => void;
}
/** React Component for the recruitment button and text on the gang main page. */
export function RecruitButton(props: IProps): React.ReactElement {
const gang = useGang();
const [open, setOpen] = useState(false);

@ -1,6 +1,3 @@
/**
* React Component for the popup used to recruit new gang members.
*/
import React, { useState } from "react";
import { Modal } from "../../ui/React/Modal";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
@ -16,6 +13,7 @@ interface IRecruitPopupProps {
onRecruit: () => void;
}
/** React Component for the popup used to recruit new gang members. */
export function RecruitModal(props: IRecruitPopupProps): React.ReactElement {
const gang = useGang();
const [name, setName] = useState("");

@ -1,6 +1,3 @@
/**
* React Component for the territory subpage.
*/
import React, { useState } from "react";
import { Container, Button, Paper, Box, Tooltip, Switch, FormControlLabel, Typography } from "@mui/material";
@ -14,6 +11,7 @@ import { AllGangs } from "../AllGangs";
import { useGang } from "./Context";
import { TerritoryInfoModal } from "./TerritoryInfoModal";
/** React Component for the territory subpage. */
export function TerritorySubpage(): React.ReactElement {
const gang = useGang();
const gangNames = Object.keys(AllGangs).filter((g) => g != gang.facName);

@ -3,9 +3,7 @@ import { Person } from "./PersonObjects/Person";
import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence";
import { Server } from "./Server/Server";
/**
* Returns the chance the person has to successfully hack a server
*/
/** Returns the chance the person has to successfully hack a server */
export function calculateHackingChance(server: Server, person: Person): number {
const hackFactor = 1.75;
const difficultyMult = (100 - server.hackDifficulty) / 100;
@ -64,9 +62,7 @@ export function calculatePercentMoneyHacked(server: Server, person: Person): num
return percentMoneyHacked;
}
/**
* Returns time it takes to complete a hack on a server, in seconds
*/
/** Returns time it takes to complete a hack on a server, in seconds */
export function calculateHackingTime(server: Server, person: Person): number {
const difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
@ -85,18 +81,14 @@ export function calculateHackingTime(server: Server, person: Person): number {
return hackingTime;
}
/**
* Returns time it takes to complete a grow operation on a server, in seconds
*/
/** Returns time it takes to complete a grow operation on a server, in seconds */
export function calculateGrowTime(server: Server, person: Person): number {
const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2
return growTimeMultiplier * calculateHackingTime(server, person);
}
/**
* Returns time it takes to complete a weaken operation on a server, in seconds
*/
/** Returns time it takes to complete a weaken operation on a server, in seconds */
export function calculateWeakenTime(server: Server, person: Person): number {
const weakenTimeMultiplier = 4; // Relative to hacking time

@ -120,16 +120,12 @@ export class HacknetNode implements IHacknetNode {
}
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("HacknetNode", this);
}
/**
* Initiatizes a HacknetNode object from a JSON save state.
*/
/** Initiatizes a HacknetNode object from a JSON save state. */
static fromJSON(value: IReviverValue): HacknetNode {
return Generic_fromJSON(HacknetNode, value.data);
}

@ -1,6 +1,3 @@
/**
* Hacknet Servers - Reworked Hacknet Node mechanic for BitNode-9
*/
import { CONSTANTS } from "../Constants";
import { IHacknetNode } from "./IHacknetNode";
@ -30,6 +27,7 @@ interface IConstructorParams {
organizationName?: string;
}
/** Hacknet Servers - Reworked Hacknet Node mechanic for BitNode-9 */
export class HacknetServer extends BaseServer implements IHacknetNode {
// Cache level. Affects hash Capacity
cache = 1;

@ -9,7 +9,6 @@
import { HashUpgrades } from "./HashUpgrades";
import { HashUpgrade } from "./HashUpgrade";
import { IMap } from "../types";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
export class HashManager {
@ -21,7 +20,7 @@ export class HashManager {
hashes = 0;
// Map of Hash Upgrade Name -> levels in that upgrade
upgrades: IMap<number> = {};
upgrades: Record<string, number> = {};
constructor() {
for (const name of Object.keys(HashUpgrades)) {
@ -29,9 +28,7 @@ export class HashManager {
}
}
/**
* Generic helper function for getting a multiplier from a HashUpgrade
*/
/** Generic helper function for getting a multiplier from a HashUpgrade */
getMult(upgName: string): number {
const upg = HashUpgrades[upgName];
const currLevel = this.upgrades[upgName];
@ -43,18 +40,14 @@ export class HashManager {
return 1 + (upg.value * currLevel) / 100;
}
/**
* One of the Hash upgrades improves studying. This returns that multiplier
*/
/** One of the Hash upgrades improves studying. This returns that multiplier */
getStudyMult(): number {
const upgName = "Improve Studying";
return this.getMult(upgName);
}
/**
* One of the Hash upgrades improves gym training. This returns that multiplier
*/
/** One of the Hash upgrades improves gym training. This returns that multiplier */
getTrainingMult(): number {
const upgName = "Improve Gym Training";
@ -70,9 +63,7 @@ export class HashManager {
return upg;
}
/**
* Get the cost (in hashes) of an upgrade
*/
/** Get the cost (in hashes) of an upgrade */
getUpgradeCost(upgName: string, count = 1): number {
const upg = this.getUpgrade(upgName);
const currLevel = this.upgrades[upgName];
@ -94,9 +85,7 @@ export class HashManager {
this.updateCapacity(0);
}
/**
* Reverts an upgrade and refunds the hashes used to buy it
*/
/** Reverts an upgrade and refunds the hashes used to buy it */
refundUpgrade(upgName: string, count = 1): void {
const upg = HashUpgrades[upgName];

@ -1,6 +1,4 @@
/**
* Object representing an upgrade that can be purchased with hashes
*/
/** Object representing an upgrade that can be purchased with hashes */
export interface IConstructorParams {
cost?: number;
costPerLevel: number;
@ -26,9 +24,7 @@ export class HashUpgrade {
*/
costPerLevel = 0;
/**
* Description of what the upgrade does
*/
/** Description of what the upgrade does */
desc = "";
/**
@ -37,7 +33,7 @@ export class HashUpgrade {
*/
hasTargetServer = false;
// Name of upgrade
/** Name of upgrade */
name = "";
// Generic value used to indicate the potency/amount of this upgrade's effect

@ -4,9 +4,8 @@
*/
import { HashUpgrade, IConstructorParams } from "./HashUpgrade";
import { HashUpgradesMetadata } from "./data/HashUpgradesMetadata";
import { IMap } from "../types";
export const HashUpgrades: IMap<HashUpgrade> = {};
export const HashUpgrades: Record<string, HashUpgrade> = {};
function createHashUpgrade(p: IConstructorParams): void {
HashUpgrades[p.name] = new HashUpgrade(p);

@ -1,6 +1,3 @@
/**
* Root React Component for the Hacknet Node UI
*/
import React, { useState, useEffect } from "react";
import { GeneralInfo } from "./GeneralInfo";
@ -29,6 +26,7 @@ import Grid from "@mui/material/Grid";
import Button from "@mui/material/Button";
import { Box } from "@mui/material";
/** Root React Component for the Hacknet Node UI */
export function HacknetRoot(): React.ReactElement {
const [open, setOpen] = useState(false);
const setRerender = useState(false)[1];

@ -1,6 +1,3 @@
/**
* Create the pop-up for purchasing upgrades with hashes
*/
import React, { useState, useEffect } from "react";
import { HashUpgrades } from "../HashUpgrades";
@ -16,6 +13,7 @@ interface IProps {
onClose: () => void;
}
/** Create the pop-up for purchasing upgrades with hashes */
export function HashUpgradeModal(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
function rerender(): void {

@ -1,6 +1,3 @@
/**
* React Component for the button that is used to purchase new Hacknet Nodes
*/
import React from "react";
import { hasHacknetServers, hasMaxNumberHacknetServers } from "../HacknetHelpers";
@ -15,6 +12,7 @@ interface IProps {
cost: number;
}
/** React Component for the button that is used to purchase new Hacknet Nodes */
export function PurchaseButton(props: IProps): React.ReactElement {
const cost = props.cost;
let text;

@ -1,10 +1,9 @@
import { CityName } from "./../Locations/data/CityNames";
import { Literature } from "./Literature";
import { LiteratureNames } from "./data/LiteratureNames";
import { IMap } from "../types";
import { FactionNames } from "../Faction/data/FactionNames";
export const Literatures: IMap<Literature> = {};
export const Literatures: Record<string, Literature> = {};
(function () {
let title, fn, txt;

@ -1,25 +1,23 @@
import { IMap } from "../../types";
export const LiteratureNames: IMap<string> = {
HackersStartingHandbook: "hackers-starting-handbook.lit",
CorporationManagementHandbook: "corporation-management-handbook.lit",
HistoryOfSynthoids: "history-of-synthoids.lit",
AGreenTomorrow: "A-Green-Tomorrow.lit",
AlphaOmega: "alpha-omega.lit",
SimulatedReality: "simulated-reality.lit",
BeyondMan: "beyond-man.lit",
BrighterThanTheSun: "brighter-than-the-sun.lit",
DemocracyIsDead: "democracy-is-dead.lit",
Sector12Crime: "sector-12-crime.lit",
ManAndMachine: "man-and-machine.lit",
SecretSocieties: "secret-societies.lit",
TheFailedFrontier: "the-failed-frontier.lit",
CodedIntelligence: "coded-intelligence.lit",
SyntheticMuscles: "synthetic-muscles.lit",
TensionsInTechRace: "tensions-in-tech-race.lit",
CostOfImmortality: "cost-of-immortality.lit",
TheHiddenWorld: "the-hidden-world.lit",
TheNewGod: "the-new-god.lit",
NewTriads: "new-triads.lit",
TheSecretWar: "the-secret-war.lit",
};
export enum LiteratureNames {
HackersStartingHandbook = "hackers-starting-handbook.lit",
CorporationManagementHandbook = "corporation-management-handbook.lit",
HistoryOfSynthoids = "history-of-synthoids.lit",
AGreenTomorrow = "A-Green-Tomorrow.lit",
AlphaOmega = "alpha-omega.lit",
SimulatedReality = "simulated-reality.lit",
BeyondMan = "beyond-man.lit",
BrighterThanTheSun = "brighter-than-the-sun.lit",
DemocracyIsDead = "democracy-is-dead.lit",
Sector12Crime = "sector-12-crime.lit",
ManAndMachine = "man-and-machine.lit",
SecretSocieties = "secret-societies.lit",
TheFailedFrontier = "the-failed-frontier.lit",
CodedIntelligence = "coded-intelligence.lit",
SyntheticMuscles = "synthetic-muscles.lit",
TensionsInTechRace = "tensions-in-tech-race.lit",
CostOfImmortality = "cost-of-immortality.lit",
TheHiddenWorld = "the-hidden-world.lit",
TheNewGod = "the-new-god.lit",
NewTriads = "new-triads.lit",
TheSecretWar = "the-secret-war.lit",
}

@ -3,6 +3,5 @@
* Key = City Name, Value = City object
*/
import { City } from "./City";
import { IMap } from "../types";
export const Cities: IMap<City> = {};
export const Cities: Record<string, City> = {};

@ -1,23 +1,15 @@
/**
* Class representing a City in the game
*/
import { CityName } from "./data/CityNames";
import { LocationName } from "./data/LocationNames";
/** Class representing a City in the game */
export class City {
/**
* List of all locations in this city
*/
/** List of all locations in this city */
locations: LocationName[];
/**
* Name of this city
*/
/** Name of this city */
name: CityName;
/**
* Metro map ascii art
*/
/** Metro map ascii art */
asciiArt: string;
constructor(name: CityName, locations: LocationName[] = [], asciiArt = "") {

@ -1,6 +1,3 @@
/**
* Class representing a visitable location in the world
*/
import { CityName } from "./data/CityNames";
import { LocationName } from "./data/LocationNames";
import { LocationType } from "./LocationTypeEnum";
@ -21,6 +18,7 @@ export interface IConstructorParams {
techVendorMinRam?: number;
}
/** Class representing a visitable location in the world */
export class Location {
/**
* Name of city this location is in. If this property is null, it means this i
@ -28,14 +26,10 @@ export class Location {
*/
city: CityName | null = null;
/**
* Cost multiplier that influences how expensive a gym/university is
*/
/** Cost multiplier that influences how expensive a gym/university is */
costMult = 0;
/**
* Exp multiplier that influences how effective a gym/university is
*/
/** Exp multiplier that influences how effective a gym/university is */
expMult = 0;
/**
@ -44,9 +38,7 @@ export class Location {
*/
infiltrationData?: IInfiltrationMetadata;
/**
* Identifier for location
*/
/** Identifier for location */
name: LocationName = LocationName.Void;
/**

@ -1,6 +1,4 @@
/**
* Enum defining the different types of possible locations
*/
/** Enum defining the different types of possible locations */
export enum LocationType {
Company,
Gym,

@ -8,9 +8,7 @@ import { Location, IConstructorParams } from "./Location";
import { CityName } from "./data/CityNames";
import { LocationsMetadata } from "./data/LocationsMetadata";
import { IMap } from "../types";
export const Locations: IMap<Location> = {};
export const Locations: Record<string, Location> = {};
/**
* Here, we'll initialize both Locations and Cities data. These can both

@ -5,10 +5,9 @@
* This map uses the official name of the city, NOT its key in the 'Cities' object
*/
import { Cities } from "./Cities";
import { IMap } from "../types";
export function createCityMap<T>(initValue: T): IMap<T> {
const map: IMap<T> = {};
export function createCityMap<T>(initValue: T): Record<string, T> {
const map: Record<string, T> = {};
const cities = Object.keys(Cities);
for (let i = 0; i < cities.length; ++i) {
map[cities[i]] = initValue;

@ -1,6 +1,4 @@
/**
* Names of all locations
*/
/** Names of all locations */
export enum LocationName {
// Aevum Locations
AevumAeroCorp = "AeroCorp",

@ -1,6 +1,3 @@
/**
* React Component for a button that's used to apply for a job
*/
import * as React from "react";
import { Company } from "../../Company/Company";
@ -18,6 +15,7 @@ type IProps = {
text: string;
};
/** React Component for a button that's used to apply for a job */
export function ApplyToJobButton(props: IProps): React.ReactElement {
function getJobRequirementTooltip(): string {
const pos = Player.getNextCompanyPosition(props.company, props.entryPosType);

@ -47,17 +47,13 @@ export function CompanyLocation(props: IProps): React.ReactElement {
const company = Companies[props.locName];
if (company == null) throw new Error(`CompanyLocation component constructed with invalid company: ${props.locName}`);
/**
* Reference to the Location that this component is being rendered for
*/
/** Reference to the Location that this component is being rendered for */
const location = Locations[props.locName];
if (location == null) {
throw new Error(`CompanyLocation component constructed with invalid location: ${props.locName}`);
}
/**
* Name of company position that player holds, if applicable
*/
/** Name of company position that player holds, if applicable */
const jobTitle = Player.jobs[props.locName] ? Player.jobs[props.locName] : null;
/**

@ -19,9 +19,7 @@ type IState = {
//Todo: Make this a functional component
export class HospitalLocation extends React.Component<Record<string, never>, IState> {
/**
* Stores button styling that sets them all to block display
*/
/** Stores button styling that sets them all to block display */
btnStyle = { display: "block" };
constructor() {

@ -1,6 +1,3 @@
/**
* React Component for the popup used to purchase a new server.
*/
import React, { useState } from "react";
import { purchaseServer } from "../../Server/ServerPurchases";
import { numeralWrapper } from "../../ui/numeralFormat";
@ -20,6 +17,7 @@ interface IProps {
rerender: () => void;
}
/** React Component for the popup used to purchase a new server. */
export function PurchaseServerModal(props: IProps): React.ReactElement {
const [hostname, setHostname] = useState("");

@ -45,9 +45,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
const inBladeburner = Player.inBladeburner();
/**
* Click handler for Bladeburner button at Sector-12 NSA
*/
/** Click handler for Bladeburner button at Sector-12 NSA */
function handleBladeburner(): void {
if (Player.inBladeburner()) {
// Enter Bladeburner division
@ -73,9 +71,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
}
}
/**
* Click handler for Resleeving button at New Tokyo VitaLife
*/
/** Click handler for Resleeving button at New Tokyo VitaLife */
function handleGrafting(): void {
Router.toGrafting();
}

@ -10,9 +10,7 @@ import { Player } from "../../Player";
import { Money } from "../../ui/React/Money";
/**
* Attempt to purchase a TOR router using the button.
*/
/** Attempt to purchase a TOR router using the button. */
export function purchaseTorRouter(): void {
if (Player.hasTorRouter()) {
dialogBoxCreate(`You already have a TOR Router!`);

@ -5,19 +5,13 @@ import { NS } from "../ScriptEditor/NetscriptDefinitions";
* Netscript functions and arguments for that script.
*/
export class Environment {
/**
* Whether or not the script that uses this Environment should stop running
*/
/** Whether or not the script that uses this Environment should stop running */
stopFlag = false;
/**
* The currently running function
*/
/** The currently running function */
runningFn = "";
/**
* Environment variables (currently only Netscript functions)
*/
/** Environment variables (currently only Netscript functions) */
vars: NS | null = null;
}

@ -2,9 +2,7 @@ import { workerScripts } from "./WorkerScripts";
let pidCounter = 1;
/**
* Find and return the next availble PID for a script
*/
/** Find and return the next availble PID for a script */
export function generateNextPid(): number {
let tempCounter = pidCounter;

@ -1,21 +1,13 @@
import { Player } from "../Player";
import { IMap } from "../types";
import { NS as INS } from "../ScriptEditor/NetscriptDefinitions";
import { INetscriptExtra } from "../NetscriptFunctions/Extra";
import { NSFull } from "../NetscriptFunctions";
/** This type assumes any value that isn't an API layer or a function has been omitted (args and enum) */
type RamCostTree<API> = {
[Property in keyof API]: API[Property] extends () => void
? number | (() => void)
: API[Property] extends object
? RamCostTree<API[Property]>
: never;
[Property in keyof API]: API[Property] extends () => unknown ? number | (() => number) : RamCostTree<API[Property]>;
};
// TODO remember to update RamCalculations.js and WorkerScript.js
// RAM costs for Netscript functions
export const RamCostConstants: IMap<number> = {
/** Constants for assigning costs to ns functions */
export const RamCostConstants: Record<string, number> = {
ScriptBaseRamCost: 1.6,
ScriptDomRamCost: 25,
ScriptCorporationRamCost: 1024 - 1.6,
@ -121,7 +113,7 @@ const hacknet = {
getHashUpgradeLevel: 0,
getStudyMult: 0,
getTrainingMult: 0,
};
} as const;
// Stock API
const stock = {
@ -150,7 +142,7 @@ const stock = {
purchase4SMarketDataTixApi: RamCostConstants.ScriptBuySellStockRamCost,
purchaseWseAccount: RamCostConstants.ScriptBuySellStockRamCost,
purchaseTixApi: RamCostConstants.ScriptBuySellStockRamCost,
};
} as const;
// Singularity API
const singularity = {
@ -209,7 +201,7 @@ const singularity = {
b1tflum3: SF4Cost(16),
destroyW0r1dD43m0n: SF4Cost(32),
getCurrentWork: SF4Cost(0.5),
};
} as const;
// Gang API
const gang = {
@ -234,7 +226,7 @@ const gang = {
setTerritoryWarfare: RamCostConstants.ScriptGangApiBaseRamCost / 2,
getChanceToWinClash: RamCostConstants.ScriptGangApiBaseRamCost,
getBonusTime: 0,
};
} as const;
// Bladeburner API
const bladeburner = {
@ -273,12 +265,12 @@ const bladeburner = {
joinBladeburnerFaction: RamCostConstants.ScriptBladeburnerApiBaseRamCost,
joinBladeburnerDivision: RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getBonusTime: 0,
};
} as const;
const infiltration = {
getPossibleLocations: RamCostConstants.ScriptInfiltrationGetLocations,
getInfiltration: RamCostConstants.ScriptInfiltrationGetInfiltrations,
};
} as const;
// Coding Contract API
const codingcontract = {
@ -287,7 +279,7 @@ const codingcontract = {
getData: RamCostConstants.ScriptCodingContractBaseRamCost / 2,
getDescription: RamCostConstants.ScriptCodingContractBaseRamCost / 2,
getNumTriesRemaining: RamCostConstants.ScriptCodingContractBaseRamCost / 5,
};
} as const;
// Duplicate Sleeve API
const sleeve = {
@ -309,7 +301,7 @@ const sleeve = {
setToBladeburnerAction: RamCostConstants.ScriptSleeveBaseRamCost,
getSleeveAugmentationPrice: RamCostConstants.ScriptSleeveBaseRamCost,
getSleeveAugmentationRepReq: RamCostConstants.ScriptSleeveBaseRamCost,
};
} as const;
// Stanek API
const stanek = {
@ -324,7 +316,7 @@ const stanek = {
getFragment: RamCostConstants.ScriptStanekFragmentAt,
removeFragment: RamCostConstants.ScriptStanekDeleteAt,
acceptGift: RamCostConstants.ScriptStanekAcceptGift,
};
} as const;
// UI API
const ui = {
@ -337,7 +329,7 @@ const ui = {
getGameInfo: 0,
clearTerminal: 0,
windowSize: 0,
};
} as const;
// Grafting API
const grafting = {
@ -345,7 +337,7 @@ const grafting = {
getAugmentationGraftTime: 3.75,
getGraftableAugmentations: 5,
graftAugmentation: 7.5,
};
} as const;
const corporation = {
getMaterialNames: 0,
@ -413,16 +405,17 @@ const corporation = {
hasResearched: 0,
setAutoJobAssignment: 0,
getOfficeSizeUpgradeCost: 0,
};
} as const;
const SourceRamCosts = {
args: undefined as unknown as never[], // special use case
enums: undefined as unknown as never,
/** RamCosts guaranteed to match ns structure 1:1 (aside from args and enums).
* An error will be generated if there are missing OR additional ram costs defined.
* To avoid errors, define every function in NetscriptDefinition.d.ts and NetscriptFunctions,
* and have a ram cost associated here. */
export const RamCosts: RamCostTree<Omit<NSFull, "args" | "enums">> = {
corporation,
hacknet,
stock,
singularity,
...singularity, // singularity is in namespace & toplevel
gang,
bladeburner,
infiltration,
@ -602,13 +595,7 @@ const SourceRamCosts = {
factionGains: 0,
},
},
};
export const RamCosts: IMap<any> = SourceRamCosts;
// This line in particular is there so typescript typechecks that we are not missing any static ram cost.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _typecheck: RamCostTree<INS & INetscriptExtra> = SourceRamCosts;
} as const;
export function getRamCost(...args: string[]): number {
if (args.length === 0) {
@ -616,7 +603,7 @@ export function getRamCost(...args: string[]): number {
return 0;
}
let curr = RamCosts[args[0]];
let curr = RamCosts[args[0] as keyof typeof RamCosts];
for (let i = 1; i < args.length; ++i) {
if (curr == null) {
console.warn(`Invalid function passed to getRamCost: ${args}`);
@ -628,7 +615,7 @@ export function getRamCost(...args: string[]): number {
break;
}
curr = curr[args[i]];
curr = curr[args[i] as keyof typeof curr];
}
if (typeof curr === "number") {

@ -13,20 +13,15 @@ import { RunningScript } from "../Script/RunningScript";
import { Script } from "../Script/Script";
import { GetServer } from "../Server/AllServers";
import { BaseServer } from "../Server/BaseServer";
import { IMap } from "../types";
import { NS } from "../ScriptEditor/NetscriptDefinitions";
import { ScriptDeath } from "./ScriptDeath";
import { ScriptArg } from "./ScriptArg";
export class WorkerScript {
/**
* Script's arguments
*/
/** Script's arguments */
args: ScriptArg[];
/**
* Copy of the script's code
*/
/** Copy of the script's code */
code = "";
/**
@ -35,52 +30,38 @@ export class WorkerScript {
*/
delay: number | null = null;
/**
* Holds the Promise reject() function while the script is "blocked" by an async op
*/
/** Holds the Promise reject() function while the script is "blocked" by an async op */
delayReject?: (reason?: ScriptDeath) => void;
/**
* Stores names of all functions that have logging disabled
*/
disableLogs: IMap<boolean> = {};
/** Stores names of all functions that have logging disabled */
disableLogs: Record<string, boolean> = {};
/**
* Used for dynamic RAM calculation. Stores names of all functions that have
* already been checked by this script.
* TODO: Could probably just combine this with loadedFns?
*/
dynamicLoadedFns: IMap<boolean> = {};
dynamicLoadedFns: Record<string, boolean> = {};
/**
* Tracks dynamic RAM usage
*/
/** Tracks dynamic RAM usage */
dynamicRamUsage: number = RamCostConstants.ScriptBaseRamCost;
/**
* Netscript Environment for this script
*/
/** Netscript Environment for this script */
env: Environment;
/**
* Status message in case of script error.
*/
/** Status message in case of script error. */
errorMessage = "";
/**
* Used for static RAM calculation. Stores names of all functions that have
* already been checked by this script
*/
loadedFns: IMap<boolean> = {};
loadedFns: Record<string, boolean> = {};
/**
* Filename of script
*/
/** Filename of script */
name: string;
/**
* Script's output/return value. Currently not used or implemented
*/
/** Script's output/return value. Currently not used or implemented */
output = "";
/**
@ -89,24 +70,16 @@ export class WorkerScript {
*/
pid: number;
/**
* Script's Static RAM usage. Equivalent to underlying script's RAM usage
*/
/** Script's Static RAM usage. Equivalent to underlying script's RAM usage */
ramUsage = 0;
/**
* Reference to underlying RunningScript object
*/
/** Reference to underlying RunningScript object */
scriptRef: RunningScript;
/**
* hostname on which this script is running
*/
/** hostname on which this script is running */
hostname: string;
/**
* Function called when the script ends.
*/
/** Function called when the script ends. */
atExit?: () => void;
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => NS) {
@ -143,9 +116,7 @@ export class WorkerScript {
}
}
/**
* Returns the Server on which this script is running
*/
/** Returns the Server on which this script is running */
getServer(): BaseServer {
const server = GetServer(this.hostname);
if (server == null) throw new Error(`Script ${this.name} pid ${this.pid} is running on non-existent server?`);

@ -1,6 +1,4 @@
/**
* Event emitter that triggers when scripts are started/stopped
*/
import { EventEmitter } from "../utils/EventEmitter";
/** Event emitter that triggers when scripts are started/stopped */
export const WorkerScriptStartStopEventEmitter = new EventEmitter<[]>();

@ -1,6 +1,4 @@
/**
* Global pool of all active scripts (scripts that are currently running)
*/
import { WorkerScript } from "./WorkerScript";
/** Global pool of all active scripts (scripts that are currently running) */
export const workerScripts: Map<number, WorkerScript> = new Map();

@ -81,7 +81,11 @@ import { InternalAPI, NetscriptContext, wrapAPI } from "./Netscript/APIWrapper";
import { INetscriptExtra } from "./NetscriptFunctions/Extra";
import { ScriptDeath } from "./Netscript/ScriptDeath";
export type NSFull = NS & INetscriptExtra;
// "Enums" as object
export const enums = {
toast: ToastVariant,
} as const;
export type NSFull = Readonly<NS & INetscriptExtra>;
export function NetscriptFunctions(workerScript: WorkerScript): NSFull {
return wrapAPI(workerScript, ns, workerScript.args.slice());
@ -89,10 +93,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NSFull {
const base: InternalAPI<NS> = {
args: [],
enums: {
toast: ToastVariant,
},
//The next line will error if enums does not match the definition in NetscriptDefinitions.d.ts
enums,
singularity: NetscriptSingularity(),
gang: NetscriptGang(),
bladeburner: NetscriptBladeburner(),
@ -1516,7 +1518,7 @@ const base: InternalAPI<NS> = {
},
tryWritePort:
(ctx: NetscriptContext) =>
(_port: unknown, data: unknown = ""): Promise<any> => {
(_port: unknown, data: unknown = ""): boolean => {
const port = helpers.number(ctx, "port", _port);
if (typeof data !== "string" && typeof data !== "number") {
throw helpers.makeRuntimeErrorMsg(
@ -1525,7 +1527,7 @@ const base: InternalAPI<NS> = {
);
}
const iport = helpers.getValidPort(ctx, port);
return Promise.resolve(iport.tryWrite(data));
return iport.tryWrite(data);
},
readPort:
(ctx: NetscriptContext) =>
@ -1788,7 +1790,7 @@ const base: InternalAPI<NS> = {
const duration = _duration === null ? null : helpers.number(ctx, "duration", _duration);
if (!checkEnum(ToastVariant, variant))
throw new Error(`variant must be one of ${Object.values(ToastVariant).join(", ")}`);
SnackbarEvents.emit(message, variant, duration);
SnackbarEvents.emit(message, variant as ToastVariant, duration);
},
prompt:
(ctx: NetscriptContext) =>
@ -1945,7 +1947,7 @@ const base: InternalAPI<NS> = {
};
// add undocumented functions
const ns = {
export const ns = {
...base,
...NetscriptExtra(),
};

@ -66,6 +66,7 @@ import { Factions } from "../Faction/Factions";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { helpers } from "../Netscript/NetscriptHelpers";
import { checkEnum } from "../utils/helpers/checkEnum";
export function NetscriptCorporation(): InternalAPI<NSCorporation> {
function createCorporation(corporationName: string, selfFund = true): boolean {
@ -711,7 +712,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
const employeeName = helpers.string(ctx, "employeeName", _employeeName);
const job = helpers.string(ctx, "job", _job);
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`);
const office = getOffice(divisionName, cityName);
AssignJob(office, employeeName, job);
@ -725,7 +726,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
const amount = helpers.number(ctx, "amount", _amount);
const job = helpers.string(ctx, "job", _job);
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`);
const office = getOffice(divisionName, cityName);
return AutoAssignJob(office, job, amount);

@ -17,9 +17,7 @@ import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { helpers } from "../Netscript/NetscriptHelpers";
export function NetscriptStockMarket(): InternalAPI<TIX> {
/**
* Checks if the player has TIX API access. Throws an error if the player does not
*/
/** Checks if the player has TIX API access. Throws an error if the player does not */
const checkTixApiAccess = function (ctx: NetscriptContext): void {
if (!player.hasWseAccount) {
throw helpers.makeRuntimeErrorMsg(ctx, `You don't have WSE Access! Cannot use ${ctx.function}()`);

@ -354,9 +354,7 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS
return true;
}
/**
* Updates the online running time stat of all running scripts
*/
/** Updates the online running time stat of all running scripts */
export function updateOnlineScriptTimes(numCycles = 1): void {
const time = (numCycles * CONSTANTS._idleSpeed) / 1000; //seconds
for (const ws of workerScripts.values()) {
@ -404,9 +402,7 @@ export function loadAllRunningScripts(): void {
}
}
/**
* Run a script from inside another script (run(), exec(), spawn(), etc.)
*/
/** Run a script from inside another script (run(), exec(), spawn(), etc.) */
export function runScriptFromScript(
caller: string,
server: BaseServer,

@ -6,7 +6,6 @@ import * as generalMethods from "./PlayerObjectGeneralMethods";
import * as serverMethods from "./PlayerObjectServerMethods";
import * as workMethods from "./PlayerObjectWorkMethods";
import { IMap } from "../../types";
import { Sleeve } from "../Sleeve/Sleeve";
import { PlayerOwnedSourceFile } from "../../SourceFile/PlayerOwnedSourceFile";
import { Exploit } from "../../Exploits/Exploit";
@ -43,7 +42,7 @@ export class PlayerObject extends Person {
hashManager = new HashManager();
hasTixApiAccess = false;
hasWseAccount = false;
jobs: IMap<string> = {};
jobs: Record<string, string> = {};
karma = 0;
numPeopleKilled = 0;
location = LocationName.TravelAgency;
@ -160,16 +159,12 @@ export class PlayerObject extends Person {
return "Player";
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("PlayerObject", this);
}
/**
* Initiatizes a PlayerObject object from a JSON save state.
*/
/** Initiatizes a PlayerObject object from a JSON save state. */
static fromJSON(value: IReviverValue): PlayerObject {
return Generic_fromJSON(PlayerObject, value.data);
}

@ -1,6 +1,4 @@
/**
* Augmentation-related methods for the Player class (PlayerObject)
*/
/** Augmentation-related methods for the Player class (PlayerObject) */
import { PlayerObject } from "./PlayerObject";
import { calculateEntropy } from "../Grafting/EntropyAccumulation";

@ -257,7 +257,7 @@ export function takeDamage(this: PlayerObject, amt: number): boolean {
export function hospitalize(this: PlayerObject): number {
const cost = getHospitalizationCost();
SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, ToastVariant.WARNING, 2000);
SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, ToastVariant.SUCCESS, 2000);
this.loseMoney(cost, "hospitalization");
this.hp.current = this.hp.max;

@ -1,6 +1,4 @@
/**
* Server and HacknetServer-related methods for the Player class (PlayerObject)
*/
// Server and HacknetServer-related methods for the Player class (PlayerObject)
import { PlayerObject } from "./PlayerObject";
import { CONSTANTS } from "../../Constants";

@ -48,9 +48,7 @@ import * as sleeveMethods from "./SleeveMethods";
export class Sleeve extends Person {
currentWork: Work | null = null;
/**
* Clone retains 'memory' synchronization (and maybe exp?) upon prestige/installing Augs
*/
/** Clone retains 'memory' synchronization (and maybe exp?) upon prestige/installing Augs */
memory = 1;
/**
@ -62,9 +60,7 @@ export class Sleeve extends Person {
*/
shock = 1;
/**
* Stored number of game "loop" cycles
*/
/** Stored number of game "loop" cycles */
storedCycles = 0;
/**
@ -100,9 +96,7 @@ export class Sleeve extends Person {
this.currentWork = null;
}
/**
* Commit crimes
*/
/** Commit crimes */
commitCrime(crimeKey: string): boolean {
const crime: Crime | null = Crimes[crimeKey] || Object.values(Crimes).find((crime) => crime.name === crimeKey);
if (!crime) {
@ -113,9 +107,7 @@ export class Sleeve extends Person {
return true;
}
/**
* Returns the cost of upgrading this sleeve's memory by a certain amount
*/
/** Returns the cost of upgrading this sleeve's memory by a certain amount */
getMemoryUpgradeCost(n: number): number {
const amt = Math.round(n);
if (amt < 0) {
@ -150,9 +142,7 @@ export class Sleeve extends Person {
this.updateSkillLevels();
}
/**
* Called on every sleeve for a Source File Prestige
*/
/** Called on every sleeve for a Source File Prestige */
prestige(): void {
// Reset exp
this.exp.hacking = 0;
@ -211,9 +201,7 @@ export class Sleeve extends Person {
return true;
}
/**
* Take a course at a university
*/
/** Take a course at a university */
takeUniversityCourse(universityName: string, className: string): boolean {
// Set exp/money multipliers based on which university.
// Also check that the sleeve is in the right city
@ -270,9 +258,7 @@ export class Sleeve extends Person {
return true;
}
/**
* Travel to another City. Costs money from player
*/
/** Travel to another City. Costs money from player */
travel(newCity: CityName): boolean {
Player.loseMoney(CONSTANTS.TravelCost, "sleeves");
this.city = newCity;
@ -354,9 +340,7 @@ export class Sleeve extends Person {
return true;
}
/**
* Begin a gym workout task
*/
/** Begin a gym workout task */
workoutAtGym(gymName: string, stat: string): boolean {
// Set exp/money multipliers based on which university.
// Also check that the sleeve is in the right city
@ -420,9 +404,7 @@ export class Sleeve extends Person {
return true;
}
/**
* Begin a bladeburner task
*/
/** Begin a bladeburner task */
bladeburner(action: string, contract: string): boolean {
if (!Player.bladeburner) return false;
switch (action) {
@ -495,16 +477,12 @@ export class Sleeve extends Person {
return "Sleeve";
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("Sleeve", this);
}
/**
* Initiatizes a Sleeve object from a JSON save state.
*/
/** Initiatizes a Sleeve object from a JSON save state. */
static fromJSON(value: IReviverValue): Sleeve {
return Generic_fromJSON(Sleeve, value.data);
}

@ -10,9 +10,7 @@ import { mergeMultipliers, Multipliers } from "../Multipliers";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { getFactionAugmentationsFiltered } from "../../Faction/FactionHelpers";
/**
* Updates this object's multipliers for the given augmentation
*/
/** Updates this object's multipliers for the given augmentation */
export function applyAugmentation(this: Sleeve, aug: Augmentation): void {
this.mults = mergeMultipliers(this.mults, aug.mults);
}

@ -1,6 +1,4 @@
/**
* Enum for different types of tasks that a Sleeve can perform
*/
/** Enum for different types of tasks that a Sleeve can perform */
export enum SleeveTaskType {
// Same Order as selectable order in UI
Idle,

@ -75,16 +75,12 @@ export class SleeveBladeburnerWork extends Work {
};
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("SleeveBladeburnerWork", this);
}
/**
* Initiatizes a BladeburnerWork object from a JSON save state.
*/
/** Initiatizes a BladeburnerWork object from a JSON save state. */
static fromJSON(value: IReviverValue): SleeveBladeburnerWork {
return Generic_fromJSON(SleeveBladeburnerWork, value.data);
}

@ -45,16 +45,12 @@ export class SleeveClassWork extends Work {
location: this.location,
};
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("SleeveClassWork", this);
}
/**
* Initiatizes a ClassWork object from a JSON save state.
*/
/** Initiatizes a ClassWork object from a JSON save state. */
static fromJSON(value: IReviverValue): SleeveClassWork {
return Generic_fromJSON(SleeveClassWork, value.data);
}

@ -49,16 +49,12 @@ export class SleeveCompanyWork extends Work {
};
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("SleeveCompanyWork", this);
}
/**
* Initiatizes a CompanyWork object from a JSON save state.
*/
/** Initiatizes a CompanyWork object from a JSON save state. */
static fromJSON(value: IReviverValue): SleeveCompanyWork {
return Generic_fromJSON(SleeveCompanyWork, value.data);
}

@ -68,16 +68,12 @@ export class SleeveCrimeWork extends Work {
};
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("SleeveCrimeWork", this);
}
/**
* Initiatizes a RecoveryWork object from a JSON save state.
*/
/** Initiatizes a RecoveryWork object from a JSON save state. */
static fromJSON(value: IReviverValue): SleeveCrimeWork {
return Generic_fromJSON(SleeveCrimeWork, value.data);
}

@ -78,16 +78,12 @@ export class SleeveFactionWork extends Work {
};
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("SleeveFactionWork", this);
}
/**
* Initiatizes a FactionWork object from a JSON save state.
*/
/** Initiatizes a FactionWork object from a JSON save state. */
static fromJSON(value: IReviverValue): SleeveFactionWork {
return Generic_fromJSON(SleeveFactionWork, value.data);
}

@ -36,16 +36,12 @@ export class SleeveInfiltrateWork extends Work {
};
}
/**
* Serialize the current object to a JSON save state.
*/
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
return Generic_toJSON("SleeveInfiltrateWork", this);
}
/**
* Initiatizes a BladeburnerWork object from a JSON save state.
*/
/** Initiatizes a BladeburnerWork object from a JSON save state. */
static fromJSON(value: IReviverValue): SleeveInfiltrateWork {
return Generic_fromJSON(SleeveInfiltrateWork, value.data);
}

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