NETSCRIPT: Type correctness for getServer (#476)

This commit is contained in:
Snarling 2023-04-11 15:12:55 -04:00 committed by GitHub
parent 561b5cbf75
commit f761eed377
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 189 additions and 179 deletions

@ -88,7 +88,7 @@
| [ReputationFormulas](./bitburner.reputationformulas.md) | Reputation formulas |
| [RunningScript](./bitburner.runningscript.md) | |
| [RunOptions](./bitburner.runoptions.md) | |
| [Server](./bitburner.server.md) | A single server. |
| [Server](./bitburner.server.md) | A server. Not all servers have all of these properties - optional properties are missing on certain servers. |
| [Singularity](./bitburner.singularity.md) | Singularity API |
| [Skills](./bitburner.skills.md) | |
| [SkillsFormulas](./bitburner.skillsformulas.md) | Skills formulas |

@ -9,5 +9,5 @@ Flag indicating whether this server has a backdoor installed by a player
**Signature:**
```typescript
backdoorInstalled: boolean;
backdoorInstalled?: boolean;
```

@ -4,10 +4,10 @@
## Server.baseDifficulty property
Initial server security level (i.e. security level when the server was created)
Server's initial server security level at creation.
**Signature:**
```typescript
baseDifficulty: number;
baseDifficulty?: number;
```

@ -4,7 +4,7 @@
## Server.cpuCores property
How many CPU cores this server has. Maximum of 8. Affects magnitude of grow and weaken.
How many CPU cores this server has. Affects magnitude of grow and weaken ran from this server.
**Signature:**

@ -4,7 +4,7 @@
## Server.ftpPortOpen property
Flag indicating whether the FTP port is open
Whether or not the FTP port is open
**Signature:**

@ -9,5 +9,5 @@ Server Security Level
**Signature:**
```typescript
hackDifficulty: number;
hackDifficulty?: number;
```

@ -4,7 +4,7 @@
## Server.httpPortOpen property
Flag indicating whether HTTP Port is open
Whether or not the HTTP Port is open
**Signature:**

@ -4,40 +4,40 @@
## Server interface
A single server.
A server. Not all servers have all of these properties - optional properties are missing on certain servers.
**Signature:**
```typescript
interface Server
export interface Server
```
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [backdoorInstalled](./bitburner.server.backdoorinstalled.md) | | boolean | Flag indicating whether this server has a backdoor installed by a player |
| [baseDifficulty](./bitburner.server.basedifficulty.md) | | number | Initial server security level (i.e. security level when the server was created) |
| [cpuCores](./bitburner.server.cpucores.md) | | number | How many CPU cores this server has. Maximum of 8. Affects magnitude of grow and weaken. |
| [ftpPortOpen](./bitburner.server.ftpportopen.md) | | boolean | Flag indicating whether the FTP port is open |
| [hackDifficulty](./bitburner.server.hackdifficulty.md) | | number | Server Security Level |
| [backdoorInstalled?](./bitburner.server.backdoorinstalled.md) | | boolean | _(Optional)_ Flag indicating whether this server has a backdoor installed by a player |
| [baseDifficulty?](./bitburner.server.basedifficulty.md) | | number | _(Optional)_ Server's initial server security level at creation. |
| [cpuCores](./bitburner.server.cpucores.md) | | number | How many CPU cores this server has. Affects magnitude of grow and weaken ran from this server. |
| [ftpPortOpen](./bitburner.server.ftpportopen.md) | | boolean | Whether or not the FTP port is open |
| [hackDifficulty?](./bitburner.server.hackdifficulty.md) | | number | _(Optional)_ Server Security Level |
| [hasAdminRights](./bitburner.server.hasadminrights.md) | | boolean | Flag indicating whether player has admin/root access to this server |
| [hostname](./bitburner.server.hostname.md) | | string | Hostname. Must be unique |
| [httpPortOpen](./bitburner.server.httpportopen.md) | | boolean | Flag indicating whether HTTP Port is open |
| [httpPortOpen](./bitburner.server.httpportopen.md) | | boolean | Whether or not the HTTP Port is open |
| [ip](./bitburner.server.ip.md) | | string | IP Address. Must be unique |
| [isConnectedTo](./bitburner.server.isconnectedto.md) | | boolean | Flag indicating whether player is currently connected to this server |
| [maxRam](./bitburner.server.maxram.md) | | number | RAM (GB) available on this server |
| [minDifficulty](./bitburner.server.mindifficulty.md) | | number | Minimum server security level that this server can be weakened to |
| [moneyAvailable](./bitburner.server.moneyavailable.md) | | number | How much money currently resides on the server and can be hacked |
| [moneyMax](./bitburner.server.moneymax.md) | | number | Maximum amount of money that this server can hold |
| [numOpenPortsRequired](./bitburner.server.numopenportsrequired.md) | | number | Number of open ports required in order to gain admin/root access |
| [openPortCount](./bitburner.server.openportcount.md) | | number | How many ports are currently opened on the server |
| [organizationName](./bitburner.server.organizationname.md) | | string | Name of company/faction/etc. that this server belongs to. Optional, not applicable to all Servers |
| [minDifficulty?](./bitburner.server.mindifficulty.md) | | number | _(Optional)_ Minimum server security level that this server can be weakened to |
| [moneyAvailable?](./bitburner.server.moneyavailable.md) | | number | _(Optional)_ How much money currently resides on the server and can be hacked |
| [moneyMax?](./bitburner.server.moneymax.md) | | number | _(Optional)_ Maximum amount of money that this server can hold |
| [numOpenPortsRequired?](./bitburner.server.numopenportsrequired.md) | | number | _(Optional)_ Number of open ports required in order to gain admin/root access |
| [openPortCount?](./bitburner.server.openportcount.md) | | number | _(Optional)_ How many ports are currently opened on the server |
| [organizationName](./bitburner.server.organizationname.md) | | string | Name of company/faction/etc. that this server belongs to, not applicable to all Servers |
| [purchasedByPlayer](./bitburner.server.purchasedbyplayer.md) | | boolean | Flag indicating whether this is a purchased server |
| [ramUsed](./bitburner.server.ramused.md) | | number | RAM (GB) used. i.e. unavailable RAM |
| [requiredHackingSkill](./bitburner.server.requiredhackingskill.md) | | number | Hacking level required to hack this server |
| [serverGrowth](./bitburner.server.servergrowth.md) | | number | Parameter that affects how effectively this server's money can be increased using the grow() Netscript function |
| [smtpPortOpen](./bitburner.server.smtpportopen.md) | | boolean | Flag indicating whether SMTP Port is open |
| [sqlPortOpen](./bitburner.server.sqlportopen.md) | | boolean | Flag indicating whether SQL Port is open |
| [sshPortOpen](./bitburner.server.sshportopen.md) | | boolean | Flag indicating whether the SSH Port is open |
| [requiredHackingSkill?](./bitburner.server.requiredhackingskill.md) | | number | _(Optional)_ Hacking level required to hack this server |
| [serverGrowth?](./bitburner.server.servergrowth.md) | | number | _(Optional)_ Growth effectiveness statistic. Higher values produce more growth with ns.grow() |
| [smtpPortOpen](./bitburner.server.smtpportopen.md) | | boolean | Whether or not the SMTP Port is open |
| [sqlPortOpen](./bitburner.server.sqlportopen.md) | | boolean | Whether or not the SQL Port is open |
| [sshPortOpen](./bitburner.server.sshportopen.md) | | boolean | Whether or not the SSH Port is open |

@ -9,5 +9,5 @@ Minimum server security level that this server can be weakened to
**Signature:**
```typescript
minDifficulty: number;
minDifficulty?: number;
```

@ -9,5 +9,5 @@ How much money currently resides on the server and can be hacked
**Signature:**
```typescript
moneyAvailable: number;
moneyAvailable?: number;
```

@ -9,5 +9,5 @@ Maximum amount of money that this server can hold
**Signature:**
```typescript
moneyMax: number;
moneyMax?: number;
```

@ -9,5 +9,5 @@ Number of open ports required in order to gain admin/root access
**Signature:**
```typescript
numOpenPortsRequired: number;
numOpenPortsRequired?: number;
```

@ -9,5 +9,5 @@ How many ports are currently opened on the server
**Signature:**
```typescript
openPortCount: number;
openPortCount?: number;
```

@ -4,7 +4,7 @@
## Server.organizationName property
Name of company/faction/etc. that this server belongs to. Optional, not applicable to all Servers
Name of company/faction/etc. that this server belongs to, not applicable to all Servers
**Signature:**

@ -9,5 +9,5 @@ Hacking level required to hack this server
**Signature:**
```typescript
requiredHackingSkill: number;
requiredHackingSkill?: number;
```

@ -4,10 +4,10 @@
## Server.serverGrowth property
Parameter that affects how effectively this server's money can be increased using the grow() Netscript function
Growth effectiveness statistic. Higher values produce more growth with ns.grow()
**Signature:**
```typescript
serverGrowth: number;
serverGrowth?: number;
```

@ -4,7 +4,7 @@
## Server.smtpPortOpen property
Flag indicating whether SMTP Port is open
Whether or not the SMTP Port is open
**Signature:**

@ -4,7 +4,7 @@
## Server.sqlPortOpen property
Flag indicating whether SQL Port is open
Whether or not the SQL Port is open
**Signature:**

@ -4,7 +4,7 @@
## Server.sshPortOpen property
Flag indicating whether the SSH Port is open
Whether or not the SSH Port is open
**Signature:**

@ -1,42 +1,37 @@
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
import { Person as IPerson } from "@nsdefs";
import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence";
import { Server } from "./Server/Server";
import { Server as IServer } from "@nsdefs";
/** Returns the chance the person has to successfully hack a server */
export function calculateHackingChance(server: Server, person: IPerson): number {
export function calculateHackingChance(server: IServer, person: IPerson): number {
const hackDifficulty = server.hackDifficulty ?? 100;
const requiredHackingSkill = server.requiredHackingSkill ?? 1e9;
// Unrooted or unhackable server
if (!server.hasAdminRights || hackDifficulty >= 100) return 0;
const hackFactor = 1.75;
const difficultyMult = (100 - server.hackDifficulty) / 100;
const difficultyMult = (100 - hackDifficulty) / 100;
const skillMult = hackFactor * person.skills.hacking;
const skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
const skillChance = (skillMult - requiredHackingSkill) / skillMult;
const chance =
skillChance *
difficultyMult *
person.mults.hacking_chance *
calculateIntelligenceBonus(person.skills.intelligence, 1);
if (chance > 1) {
return 1;
}
if (chance < 0) {
return 0;
}
return chance;
return Math.min(1, Math.max(chance, 0));
}
/**
* Returns the amount of hacking experience the person will gain upon
* successfully hacking a server
*/
export function calculateHackingExpGain(server: Server, person: IPerson): number {
export function calculateHackingExpGain(server: IServer, person: IPerson): number {
const baseDifficulty = server.baseDifficulty;
if (!baseDifficulty) return 0;
const baseExpGain = 3;
const diffFactor = 0.3;
if (server.baseDifficulty == null) {
server.baseDifficulty = server.hackDifficulty;
}
let expGain = baseExpGain;
expGain += server.baseDifficulty * diffFactor;
expGain += baseDifficulty * diffFactor;
return expGain * person.mults.hacking_exp * BitNodeMultipliers.HackExpGain;
}
@ -44,27 +39,27 @@ export function calculateHackingExpGain(server: Server, person: IPerson): number
* Returns the percentage of money that will be stolen from a server if
* it is successfully hacked (returns the decimal form, not the actual percent value)
*/
export function calculatePercentMoneyHacked(server: Server, person: IPerson): number {
export function calculatePercentMoneyHacked(server: IServer, person: IPerson): number {
const hackDifficulty = server.hackDifficulty ?? 100;
if (hackDifficulty >= 100) return 0;
const requiredHackingSkill = server.requiredHackingSkill ?? 1e9;
// Adjust if needed for balancing. This is the divisor for the final calculation
const balanceFactor = 240;
const difficultyMult = (100 - server.hackDifficulty) / 100;
const skillMult = (person.skills.hacking - (server.requiredHackingSkill - 1)) / person.skills.hacking;
const difficultyMult = (100 - hackDifficulty) / 100;
const skillMult = (person.skills.hacking - (requiredHackingSkill - 1)) / person.skills.hacking;
const percentMoneyHacked =
(difficultyMult * skillMult * person.mults.hacking_money * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
if (percentMoneyHacked < 0) {
return 0;
}
if (percentMoneyHacked > 1) {
return 1;
}
return percentMoneyHacked;
return Math.min(1, Math.max(percentMoneyHacked, 0));
}
/** Returns time it takes to complete a hack on a server, in seconds */
export function calculateHackingTime(server: Server, person: IPerson): number {
const difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
export function calculateHackingTime(server: IServer, person: IPerson): number {
const hackDifficulty = server.hackDifficulty;
const requiredHackingSkill = server.requiredHackingSkill;
if (!hackDifficulty || !requiredHackingSkill) return Infinity;
const difficultyMult = requiredHackingSkill * hackDifficulty;
const baseDiff = 500;
const baseSkill = 50;
@ -82,14 +77,14 @@ export function calculateHackingTime(server: Server, person: IPerson): number {
}
/** Returns time it takes to complete a grow operation on a server, in seconds */
export function calculateGrowTime(server: Server, person: IPerson): number {
export function calculateGrowTime(server: IServer, person: IPerson): 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 */
export function calculateWeakenTime(server: Server, person: IPerson): number {
export function calculateWeakenTime(server: IServer, person: IPerson): number {
const weakenTimeMultiplier = 4; // Relative to hacking time
return weakenTimeMultiplier * calculateHackingTime(server, person);

@ -6,7 +6,7 @@ import { ScriptDeath } from "./ScriptDeath";
import { formatExp, formatMoney, formatRam, formatThreads } from "../ui/formatNumber";
import { ScriptArg } from "./ScriptArg";
import { CityName } from "../Enums";
import { BasicHGWOptions, RunningScript as IRunningScript, Person as IPerson } from "@nsdefs";
import { BasicHGWOptions, RunningScript as IRunningScript, Person as IPerson, Server as IServer } from "@nsdefs";
import { Server } from "../Server/Server";
import {
calculateHackingChance,
@ -597,36 +597,26 @@ function person(ctx: NetscriptContext, p: unknown): IPerson {
return p as IPerson;
}
function server(ctx: NetscriptContext, s: unknown): Server {
function server(ctx: NetscriptContext, s: unknown): IServer {
const fakeServer = {
cpuCores: undefined,
ftpPortOpen: undefined,
hasAdminRights: undefined,
hostname: undefined,
httpPortOpen: undefined,
ip: undefined,
sshPortOpen: undefined,
ftpPortOpen: undefined,
smtpPortOpen: undefined,
httpPortOpen: undefined,
sqlPortOpen: undefined,
hasAdminRights: undefined,
cpuCores: undefined,
isConnectedTo: undefined,
ramUsed: undefined,
maxRam: undefined,
organizationName: undefined,
ramUsed: undefined,
smtpPortOpen: undefined,
sqlPortOpen: undefined,
sshPortOpen: undefined,
purchasedByPlayer: undefined,
backdoorInstalled: undefined,
baseDifficulty: undefined,
hackDifficulty: undefined,
minDifficulty: undefined,
moneyAvailable: undefined,
moneyMax: undefined,
numOpenPortsRequired: undefined,
openPortCount: undefined,
requiredHackingSkill: undefined,
serverGrowth: undefined,
};
const error = missingKey(fakeServer, s);
if (error) throw makeRuntimeErrorMsg(ctx, `server should be a hackable Server.\n${error}`, "TYPE");
return s as Server;
if (error) throw makeRuntimeErrorMsg(ctx, `server should be a Server.\n${error}`, "TYPE");
return s as IServer;
}
function missingKey(expect: object, actual: unknown): string | false {

@ -985,11 +985,36 @@ export const ns: InternalAPI<NSFull> = {
return Object.assign({}, getBitNodeMultipliers(n, lvl));
},
getServer:
(ctx) =>
(_hostname = ctx.workerScript.hostname) => {
const hostname = helpers.string(ctx, "hostname", _hostname);
getServer: (ctx) => (_hostname) => {
const hostname = helpers.string(ctx, "hostname", _hostname ?? ctx.workerScript.hostname);
const server = helpers.getServer(ctx, hostname);
return {
hostname: server.hostname,
ip: server.ip,
sshPortOpen: server.sshPortOpen,
ftpPortOpen: server.ftpPortOpen,
smtpPortOpen: server.smtpPortOpen,
httpPortOpen: server.httpPortOpen,
sqlPortOpen: server.sqlPortOpen,
hasAdminRights: server.hasAdminRights,
cpuCores: server.cpuCores,
isConnectedTo: server.isConnectedTo,
ramUsed: server.ramUsed,
maxRam: server.maxRam,
organizationName: server.organizationName,
purchasedByPlayer: server.purchasedByPlayer,
backdoorInstalled: server.backdoorInstalled,
baseDifficulty: server.baseDifficulty,
hackDifficulty: server.hackDifficulty,
minDifficulty: server.minDifficulty,
moneyAvailable: server.moneyAvailable,
moneyMax: server.moneyMax,
numOpenPortsRequired: server.numOpenPortsRequired,
openPortCount: server.openPortCount,
requiredHackingSkill: server.requiredHackingSkill,
serverGrowth: server.serverGrowth,
};
const copy = Object.assign({}, server) as Server;
// These fields should be hidden.
copy.contracts = [];

@ -454,93 +454,75 @@ interface HacknetServerConstants {
}
/**
* A single server.
* A server. Not all servers have all of these properties - optional properties are missing on certain servers.
* @public
*/
interface Server {
/**
* How many CPU cores this server has. Maximum of 8.
* Affects magnitude of grow and weaken.
*/
cpuCores: number;
export interface Server {
/** Hostname. Must be unique */
hostname: string;
/** IP Address. Must be unique */
ip: string;
/** Flag indicating whether the FTP port is open */
/** Whether or not the SSH Port is open */
sshPortOpen: boolean;
/** Whether or not the FTP port is open */
ftpPortOpen: boolean;
/** Whether or not the SMTP Port is open */
smtpPortOpen: boolean;
/** Whether or not the HTTP Port is open */
httpPortOpen: boolean;
/** Whether or not the SQL Port is open */
sqlPortOpen: boolean;
/** Flag indicating whether player has admin/root access to this server */
hasAdminRights: boolean;
/** Hostname. Must be unique */
hostname: string;
/** Flag indicating whether HTTP Port is open */
httpPortOpen: boolean;
/** IP Address. Must be unique */
ip: string;
/** How many CPU cores this server has. Affects magnitude of grow and weaken ran from this server. */
cpuCores: number;
/** Flag indicating whether player is currently connected to this server */
isConnectedTo: boolean;
/** RAM (GB) used. i.e. unavailable RAM */
ramUsed: number;
/** RAM (GB) available on this server */
maxRam: number;
/**
* Name of company/faction/etc. that this server belongs to.
* Optional, not applicable to all Servers
*/
/** Name of company/faction/etc. that this server belongs to, not applicable to all Servers */
organizationName: string;
/** RAM (GB) used. i.e. unavailable RAM */
ramUsed: number;
/** Flag indicating whether SMTP Port is open */
smtpPortOpen: boolean;
/** Flag indicating whether SQL Port is open */
sqlPortOpen: boolean;
/** Flag indicating whether the SSH Port is open */
sshPortOpen: boolean;
/** Flag indicating whether this is a purchased server */
purchasedByPlayer: boolean;
/** Flag indicating whether this server has a backdoor installed by a player */
backdoorInstalled: boolean;
backdoorInstalled?: boolean;
/**
* Initial server security level
* (i.e. security level when the server was created)
*/
baseDifficulty: number;
/** Server's initial server security level at creation. */
baseDifficulty?: number;
/** Server Security Level */
hackDifficulty: number;
hackDifficulty?: number;
/** Minimum server security level that this server can be weakened to */
minDifficulty: number;
minDifficulty?: number;
/** How much money currently resides on the server and can be hacked */
moneyAvailable: number;
moneyAvailable?: number;
/** Maximum amount of money that this server can hold */
moneyMax: number;
moneyMax?: number;
/** Number of open ports required in order to gain admin/root access */
numOpenPortsRequired: number;
numOpenPortsRequired?: number;
/** How many ports are currently opened on the server */
openPortCount: number;
openPortCount?: number;
/** Hacking level required to hack this server */
requiredHackingSkill: number;
requiredHackingSkill?: number;
/**
* Parameter that affects how effectively this server's money can
* be increased using the grow() Netscript function
*/
serverGrowth: number;
/** Growth effectiveness statistic. Higher values produce more growth with ns.grow() */
serverGrowth?: number;
}
/**

@ -1,3 +1,4 @@
import type { Server as IServer } from "@nsdefs";
import { CodingContract } from "../CodingContracts";
import { RunningScript } from "../Script/RunningScript";
import { Script } from "../Script/Script";
@ -26,7 +27,7 @@ interface writeResult {
}
/** Abstract Base Class for any Server object */
export abstract class BaseServer {
export abstract class BaseServer implements IServer {
// Coding Contract files on this server
contracts: CodingContract[] = [];
@ -93,8 +94,17 @@ export abstract class BaseServer {
// Flag indicating whether this is a purchased server
purchasedByPlayer = false;
// Variables that exist only on some types of servers can just be optional.
// Optional, listed just so they can be accessed on a BaseServer. These will be undefined for HacknetServers.
backdoorInstalled?: boolean;
baseDifficulty?: number;
hackDifficulty?: number;
minDifficulty?: number;
moneyAvailable?: number;
moneyMax?: number;
numOpenPortsRequired?: number;
openPortCount?: number;
requiredHackingSkill?: number;
serverGrowth?: number;
constructor(params: IConstructorParams = { hostname: "", ip: createRandomIp() }) {
this.ip = params.ip ? params.ip : createRandomIp();

@ -10,6 +10,7 @@ import { Programs } from "../Programs/Programs";
import { LiteratureNames } from "../Literature/data/LiteratureNames";
import { Person as IPerson } from "@nsdefs";
import { isValidNumber } from "../utils/helpers/isValidNumber";
import { Server as IServer } from "@nsdefs";
/**
* Constructs a new server, while also ensuring that the new server
@ -48,8 +49,10 @@ export function safelyCreateUniqueServer(params: IConstructorParams): Server {
* @param p - Reference to Player object
* @returns Number of "growth cycles" needed
*/
export function numCycleForGrowth(server: Server, growth: number, cores = 1): number {
let ajdGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / server.hackDifficulty;
export function numCycleForGrowth(server: IServer, growth: number, cores = 1): number {
if (!server.serverGrowth) return Infinity;
const hackDifficulty = server.hackDifficulty ?? 100;
let ajdGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / hackDifficulty;
if (ajdGrowthRate > CONSTANTS.ServerMaxGrowthRate) {
ajdGrowthRate = CONSTANTS.ServerMaxGrowthRate;
}
@ -79,18 +82,22 @@ export function numCycleForGrowth(server: Server, growth: number, cores = 1): nu
* @returns Integer threads needed by a single ns.grow call to reach targetMoney from startMoney.
*/
export function numCycleForGrowthCorrected(
server: Server,
server: IServer,
targetMoney: number,
startMoney: number,
cores = 1,
person: IPerson = Player,
): number {
if (!server.serverGrowth) return Infinity;
const moneyMax = server.moneyMax ?? 1;
const hackDifficulty = server.hackDifficulty ?? 100;
if (startMoney < 0) startMoney = 0; // servers "can't" have less than 0 dollars on them
if (targetMoney > server.moneyMax) targetMoney = server.moneyMax; // can't grow a server to more than its moneyMax
if (targetMoney > moneyMax) targetMoney = moneyMax; // can't grow a server to more than its moneyMax
if (targetMoney <= startMoney) return 0; // no growth --> no threads
// exponential base adjusted by security
const adjGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / server.hackDifficulty;
const adjGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / hackDifficulty;
const exponentialBase = Math.min(adjGrowthRate, CONSTANTS.ServerMaxGrowthRate); // cap growth rate
// total of all grow thread multipliers

@ -1,14 +1,15 @@
import { CONSTANTS } from "../../Constants";
import { Server } from "../Server";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Person as IPerson } from "@nsdefs";
import { Person as IPerson, Server as IServer } from "@nsdefs";
export function calculateServerGrowth(server: Server, threads: number, p: IPerson, cores = 1): number {
export function calculateServerGrowth(server: IServer, threads: number, p: IPerson, cores = 1): number {
if (!server.serverGrowth) return 0;
const hackDifficulty = server.hackDifficulty ?? 100;
const numServerGrowthCycles = Math.max(Math.floor(threads), 0);
//Get adjusted growth rate, which accounts for server security
const growthRate = CONSTANTS.ServerBaseGrowthRate;
let adjGrowthRate = 1 + (growthRate - 1) / server.hackDifficulty;
let adjGrowthRate = 1 + (growthRate - 1) / hackDifficulty;
if (adjGrowthRate > CONSTANTS.ServerMaxGrowthRate) {
adjGrowthRate = CONSTANTS.ServerMaxGrowthRate;
}