2022-08-09 21:41:47 +02:00
|
|
|
import { Player as player } from "../Player";
|
2021-10-14 09:22:02 +02:00
|
|
|
import { calculateServerGrowth } from "../Server/formulas/grow";
|
2023-02-14 23:38:51 +01:00
|
|
|
import { numCycleForGrowthCorrected } from "../Server/ServerHelpers";
|
2021-10-14 09:22:02 +02:00
|
|
|
import {
|
|
|
|
calculateMoneyGainRate,
|
|
|
|
calculateLevelUpgradeCost,
|
|
|
|
calculateRamUpgradeCost,
|
|
|
|
calculateCoreUpgradeCost,
|
|
|
|
calculateNodeCost,
|
|
|
|
} from "../Hacknet/formulas/HacknetNodes";
|
|
|
|
import {
|
|
|
|
calculateHashGainRate as HScalculateHashGainRate,
|
|
|
|
calculateLevelUpgradeCost as HScalculateLevelUpgradeCost,
|
|
|
|
calculateRamUpgradeCost as HScalculateRamUpgradeCost,
|
|
|
|
calculateCoreUpgradeCost as HScalculateCoreUpgradeCost,
|
|
|
|
calculateCacheUpgradeCost as HScalculateCacheUpgradeCost,
|
|
|
|
calculateServerCost as HScalculateServerCost,
|
|
|
|
} from "../Hacknet/formulas/HacknetServers";
|
|
|
|
import { HacknetNodeConstants, HacknetServerConstants } from "../Hacknet/data/Constants";
|
|
|
|
import { calculateSkill, calculateExp } from "../PersonObjects/formulas/skill";
|
|
|
|
import {
|
|
|
|
calculateHackingChance,
|
|
|
|
calculateHackingExpGain,
|
|
|
|
calculatePercentMoneyHacked,
|
|
|
|
calculateHackingTime,
|
|
|
|
calculateGrowTime,
|
|
|
|
calculateWeakenTime,
|
|
|
|
} from "../Hacking";
|
FILES: Path rework & typesafety (#479)
* Added new types for various file paths, all in the Paths folder.
* TypeSafety and other helper functions related to these types
* Added basic globbing support with * and ?. Currently only implemented for Script/Text, on nano and download terminal commands
* Enforcing the new types throughout the codebase, plus whatever rewrites happened along the way
* Server.textFiles is now a map
* TextFile no longer uses a fn property, now it is filename
* Added a shared ContentFile interface for shared functionality between TextFile and Script.
* related to ContentFile change above, the player is now allowed to move a text file to a script file and vice versa.
* File paths no longer conditionally start with slashes, and all directory names other than root have ending slashes. The player is still able to provide paths starting with / but this now indicates that the player is specifying an absolute path instead of one relative to root.
* Singularized the MessageFilename and LiteratureName enums
* Because they now only accept correct types, server.writeToXFile functions now always succeed (the only reasons they could fail before were invalid filepath).
* Fix several issues with tab completion, which included pretty much a complete rewrite
* Changed the autocomplete display options so there's less chance it clips outside the display area.
* Turned CompletedProgramName into an enum.
* Got rid of programsMetadata, and programs and DarkWebItems are now initialized immediately instead of relying on initializers called from the engine.
* For any executable (program, cct, or script file) pathing can be used directly to execute without using the run command (previously the command had to start with ./ and it wasn't actually using pathing).
2023-04-24 16:26:57 +02:00
|
|
|
import { CompletedProgramName } from "../Programs/Programs";
|
2022-12-30 02:28:53 +01:00
|
|
|
import { Formulas as IFormulas, Player as IPlayer, Person as IPerson } from "@nsdefs";
|
2021-12-09 00:19:30 +01:00
|
|
|
import {
|
|
|
|
calculateRespectGain,
|
|
|
|
calculateWantedLevelGain,
|
|
|
|
calculateMoneyGain,
|
|
|
|
calculateWantedPenalty,
|
2021-12-09 18:52:51 +01:00
|
|
|
calculateAscensionMult,
|
|
|
|
calculateAscensionPointsGain,
|
2021-12-09 00:19:30 +01:00
|
|
|
} from "../Gang/formulas/formulas";
|
2022-03-31 21:52:03 +02:00
|
|
|
import { favorToRep as calculateFavorToRep, repToFavor as calculateRepToFavor } from "../Faction/formulas/favor";
|
2022-04-14 20:01:31 +02:00
|
|
|
import { repFromDonation } from "../Faction/formulas/donation";
|
2022-12-30 02:28:53 +01:00
|
|
|
import { InternalAPI, NetscriptContext, removedFunction } from "../Netscript/APIWrapper";
|
2022-08-08 19:43:41 +02:00
|
|
|
import { helpers } from "../Netscript/NetscriptHelpers";
|
2022-11-06 23:27:04 +01:00
|
|
|
import { calculateCrimeWorkStats } from "../Work/Formulas";
|
|
|
|
import { calculateCompanyWorkStats } from "../Work/Formulas";
|
|
|
|
import { Companies } from "../Company/Companies";
|
|
|
|
import { calculateClassEarnings } from "../Work/Formulas";
|
|
|
|
import { calculateFactionExp, calculateFactionRep } from "../Work/Formulas";
|
2022-12-30 02:28:53 +01:00
|
|
|
import { FactionWorkType, GymType, UniversityClassType, LocationName, CityName } from "../Enums";
|
2021-10-14 09:22:02 +02:00
|
|
|
|
2022-08-23 22:01:34 +02:00
|
|
|
import { defaultMultipliers } from "../PersonObjects/Multipliers";
|
2022-11-20 14:37:11 +01:00
|
|
|
import { checkEnum, findEnumMember } from "../utils/helpers/enum";
|
2022-12-30 02:28:53 +01:00
|
|
|
import { JobName } from "../Enums";
|
2022-11-06 23:27:04 +01:00
|
|
|
import { CompanyPositions } from "../Company/CompanyPositions";
|
2022-11-20 14:37:11 +01:00
|
|
|
import { findCrime } from "../Crime/CrimeHelpers";
|
2022-08-23 22:01:34 +02:00
|
|
|
|
2022-08-09 21:41:47 +02:00
|
|
|
export function NetscriptFormulas(): InternalAPI<IFormulas> {
|
2022-05-24 23:29:44 +02:00
|
|
|
const checkFormulasAccess = function (ctx: NetscriptContext): void {
|
FILES: Path rework & typesafety (#479)
* Added new types for various file paths, all in the Paths folder.
* TypeSafety and other helper functions related to these types
* Added basic globbing support with * and ?. Currently only implemented for Script/Text, on nano and download terminal commands
* Enforcing the new types throughout the codebase, plus whatever rewrites happened along the way
* Server.textFiles is now a map
* TextFile no longer uses a fn property, now it is filename
* Added a shared ContentFile interface for shared functionality between TextFile and Script.
* related to ContentFile change above, the player is now allowed to move a text file to a script file and vice versa.
* File paths no longer conditionally start with slashes, and all directory names other than root have ending slashes. The player is still able to provide paths starting with / but this now indicates that the player is specifying an absolute path instead of one relative to root.
* Singularized the MessageFilename and LiteratureName enums
* Because they now only accept correct types, server.writeToXFile functions now always succeed (the only reasons they could fail before were invalid filepath).
* Fix several issues with tab completion, which included pretty much a complete rewrite
* Changed the autocomplete display options so there's less chance it clips outside the display area.
* Turned CompletedProgramName into an enum.
* Got rid of programsMetadata, and programs and DarkWebItems are now initialized immediately instead of relying on initializers called from the engine.
* For any executable (program, cct, or script file) pathing can be used directly to execute without using the run command (previously the command had to start with ./ and it wasn't actually using pathing).
2023-04-24 16:26:57 +02:00
|
|
|
if (!player.hasProgram(CompletedProgramName.formulas)) {
|
2022-08-08 19:43:41 +02:00
|
|
|
throw helpers.makeRuntimeErrorMsg(ctx, `Requires Formulas.exe to run.`);
|
2021-10-14 09:22:02 +02:00
|
|
|
}
|
|
|
|
};
|
2022-12-30 02:28:53 +01:00
|
|
|
const formulasFunctions: InternalAPI<IFormulas> = {
|
2022-10-12 14:49:27 +02:00
|
|
|
mockServer: () => () => ({
|
2022-08-23 22:01:34 +02:00
|
|
|
cpuCores: 0,
|
|
|
|
ftpPortOpen: false,
|
|
|
|
hasAdminRights: false,
|
|
|
|
hostname: "",
|
|
|
|
httpPortOpen: false,
|
|
|
|
ip: "",
|
|
|
|
isConnectedTo: false,
|
|
|
|
maxRam: 0,
|
|
|
|
organizationName: "",
|
|
|
|
ramUsed: 0,
|
|
|
|
smtpPortOpen: false,
|
|
|
|
sqlPortOpen: false,
|
|
|
|
sshPortOpen: false,
|
|
|
|
purchasedByPlayer: false,
|
|
|
|
backdoorInstalled: false,
|
|
|
|
baseDifficulty: 0,
|
|
|
|
hackDifficulty: 0,
|
|
|
|
minDifficulty: 0,
|
|
|
|
moneyAvailable: 0,
|
|
|
|
moneyMax: 0,
|
|
|
|
numOpenPortsRequired: 0,
|
|
|
|
openPortCount: 0,
|
|
|
|
requiredHackingSkill: 0,
|
|
|
|
serverGrowth: 0,
|
|
|
|
}),
|
2022-11-09 13:26:26 +01:00
|
|
|
mockPlayer: () => (): IPlayer => ({
|
2022-08-23 22:01:34 +02:00
|
|
|
hp: { current: 0, max: 0 },
|
2022-11-09 13:26:26 +01:00
|
|
|
skills: { hacking: 0, strength: 0, defense: 0, dexterity: 0, agility: 0, charisma: 0, intelligence: 0 },
|
|
|
|
exp: { hacking: 0, strength: 0, defense: 0, dexterity: 0, agility: 0, charisma: 0, intelligence: 0 },
|
2022-08-23 22:01:34 +02:00
|
|
|
mults: defaultMultipliers(),
|
|
|
|
numPeopleKilled: 0,
|
|
|
|
money: 0,
|
2022-12-30 02:28:53 +01:00
|
|
|
city: CityName.Sector12,
|
2023-04-18 09:19:45 +02:00
|
|
|
location: LocationName.TravelAgency,
|
2022-08-23 22:01:34 +02:00
|
|
|
bitNodeN: 0,
|
|
|
|
totalPlaytime: 0,
|
|
|
|
jobs: {},
|
|
|
|
factions: [],
|
|
|
|
entropy: 0,
|
|
|
|
}),
|
2022-11-09 13:26:26 +01:00
|
|
|
mockPerson: () => (): IPerson => ({
|
|
|
|
hp: { current: 0, max: 0 },
|
|
|
|
skills: { hacking: 0, strength: 0, defense: 0, dexterity: 0, agility: 0, charisma: 0, intelligence: 0 },
|
|
|
|
exp: { hacking: 0, strength: 0, defense: 0, dexterity: 0, agility: 0, charisma: 0, intelligence: 0 },
|
|
|
|
mults: defaultMultipliers(),
|
2022-12-30 02:28:53 +01:00
|
|
|
city: CityName.Sector12,
|
2022-11-09 13:26:26 +01:00
|
|
|
}),
|
2022-03-31 21:52:03 +02:00
|
|
|
reputation: {
|
2022-10-12 14:49:27 +02:00
|
|
|
calculateFavorToRep: (ctx) => (_favor) => {
|
|
|
|
const favor = helpers.number(ctx, "favor", _favor);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateFavorToRep(favor);
|
|
|
|
},
|
|
|
|
calculateRepToFavor: (ctx) => (_rep) => {
|
|
|
|
const rep = helpers.number(ctx, "rep", _rep);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateRepToFavor(rep);
|
|
|
|
},
|
|
|
|
repFromDonation: (ctx) => (_amount, _player) => {
|
|
|
|
const amount = helpers.number(ctx, "amount", _amount);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _player);
|
2022-10-12 14:49:27 +02:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
return repFromDonation(amount, person);
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
2022-03-31 21:27:02 +02:00
|
|
|
},
|
2021-11-03 03:58:40 +01:00
|
|
|
skills: {
|
2022-05-24 23:29:44 +02:00
|
|
|
calculateSkill:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_exp, _mult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const exp = helpers.number(ctx, "exp", _exp);
|
|
|
|
const mult = helpers.number(ctx, "mult", _mult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateSkill(exp, mult);
|
|
|
|
},
|
|
|
|
calculateExp:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_skill, _mult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const skill = helpers.number(ctx, "skill", _skill);
|
|
|
|
const mult = helpers.number(ctx, "mult", _mult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateExp(skill, mult);
|
|
|
|
},
|
2021-11-03 03:58:40 +01:00
|
|
|
},
|
|
|
|
hacking: {
|
2022-10-12 14:49:27 +02:00
|
|
|
hackChance: (ctx) => (_server, _player) => {
|
|
|
|
const server = helpers.server(ctx, _server);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _player);
|
2022-10-12 14:49:27 +02:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
return calculateHackingChance(server, person);
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
|
|
|
hackExp: (ctx) => (_server, _player) => {
|
|
|
|
const server = helpers.server(ctx, _server);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _player);
|
2022-10-12 14:49:27 +02:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
return calculateHackingExpGain(server, person);
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
|
|
|
hackPercent: (ctx) => (_server, _player) => {
|
|
|
|
const server = helpers.server(ctx, _server);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _player);
|
2022-10-12 14:49:27 +02:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
return calculatePercentMoneyHacked(server, person);
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
2023-02-14 23:38:51 +01:00
|
|
|
/* TODO 2.3: Remove growPercent, add growMultiplier function?
|
|
|
|
Much better name given the output. Not sure if removedFunction error dialog/editing script will be too annoying.
|
|
|
|
Changing the function name also allows reordering params as server, player, etc. like other formulas functions */
|
2022-05-24 23:29:44 +02:00
|
|
|
growPercent:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_server, _threads, _player, _cores = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const server = helpers.server(ctx, _server);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _player);
|
2022-08-08 19:43:41 +02:00
|
|
|
const threads = helpers.number(ctx, "threads", _threads);
|
|
|
|
const cores = helpers.number(ctx, "cores", _cores);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
return calculateServerGrowth(server, threads, person, cores);
|
2022-05-24 23:29:44 +02:00
|
|
|
},
|
2023-02-14 23:38:51 +01:00
|
|
|
growThreads:
|
|
|
|
(ctx) =>
|
|
|
|
(_server, _player, _targetMoney, _cores = 1) => {
|
|
|
|
const server = helpers.server(ctx, _server);
|
|
|
|
const player = helpers.person(ctx, _player);
|
|
|
|
const targetMoney = helpers.number(ctx, "targetMoney", _targetMoney);
|
|
|
|
const startMoney = helpers.number(ctx, "server.moneyAvailable", server.moneyAvailable);
|
|
|
|
const cores = helpers.number(ctx, "cores", _cores);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return numCycleForGrowthCorrected(server, targetMoney, startMoney, cores, player);
|
|
|
|
},
|
2022-10-12 14:49:27 +02:00
|
|
|
hackTime: (ctx) => (_server, _player) => {
|
|
|
|
const server = helpers.server(ctx, _server);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _player);
|
2022-10-12 14:49:27 +02:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
return calculateHackingTime(server, person) * 1000;
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
|
|
|
growTime: (ctx) => (_server, _player) => {
|
|
|
|
const server = helpers.server(ctx, _server);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _player);
|
2022-10-12 14:49:27 +02:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
return calculateGrowTime(server, person) * 1000;
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
|
|
|
weakenTime: (ctx) => (_server, _player) => {
|
|
|
|
const server = helpers.server(ctx, _server);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _player);
|
2022-10-12 14:49:27 +02:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
return calculateWeakenTime(server, person) * 1000;
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
2021-10-14 09:22:02 +02:00
|
|
|
},
|
|
|
|
hacknetNodes: {
|
2022-05-24 23:29:44 +02:00
|
|
|
moneyGainRate:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_level, _ram, _cores, _mult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const level = helpers.number(ctx, "level", _level);
|
|
|
|
const ram = helpers.number(ctx, "ram", _ram);
|
|
|
|
const cores = helpers.number(ctx, "cores", _cores);
|
|
|
|
const mult = helpers.number(ctx, "mult", _mult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateMoneyGainRate(level, ram, cores, mult);
|
|
|
|
},
|
|
|
|
levelUpgradeCost:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_startingLevel, _extraLevels = 1, _costMult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const startingLevel = helpers.number(ctx, "startingLevel", _startingLevel);
|
|
|
|
const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels);
|
|
|
|
const costMult = helpers.number(ctx, "costMult", _costMult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
|
|
|
|
},
|
|
|
|
ramUpgradeCost:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_startingRam, _extraLevels = 1, _costMult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const startingRam = helpers.number(ctx, "startingRam", _startingRam);
|
|
|
|
const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels);
|
|
|
|
const costMult = helpers.number(ctx, "costMult", _costMult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateRamUpgradeCost(startingRam, extraLevels, costMult);
|
|
|
|
},
|
|
|
|
coreUpgradeCost:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_startingCore, _extraCores = 1, _costMult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const startingCore = helpers.number(ctx, "startingCore", _startingCore);
|
|
|
|
const extraCores = helpers.number(ctx, "extraCores", _extraCores);
|
|
|
|
const costMult = helpers.number(ctx, "costMult", _costMult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateCoreUpgradeCost(startingCore, extraCores, costMult);
|
|
|
|
},
|
2022-10-12 14:49:27 +02:00
|
|
|
hacknetNodeCost: (ctx) => (_n, _mult) => {
|
|
|
|
const n = helpers.number(ctx, "n", _n);
|
|
|
|
const mult = helpers.number(ctx, "mult", _mult);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateNodeCost(n, mult);
|
|
|
|
},
|
|
|
|
constants: (ctx) => () => {
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
2021-10-14 09:22:02 +02:00
|
|
|
return Object.assign({}, HacknetNodeConstants);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
hacknetServers: {
|
2022-05-24 23:29:44 +02:00
|
|
|
hashGainRate:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_level, _ramUsed, _maxRam, _cores, _mult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const level = helpers.number(ctx, "level", _level);
|
|
|
|
const ramUsed = helpers.number(ctx, "ramUsed", _ramUsed);
|
|
|
|
const maxRam = helpers.number(ctx, "maxRam", _maxRam);
|
|
|
|
const cores = helpers.number(ctx, "cores", _cores);
|
|
|
|
const mult = helpers.number(ctx, "mult", _mult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return HScalculateHashGainRate(level, ramUsed, maxRam, cores, mult);
|
|
|
|
},
|
|
|
|
levelUpgradeCost:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_startingLevel, _extraLevels = 1, _costMult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const startingLevel = helpers.number(ctx, "startingLevel", _startingLevel);
|
|
|
|
const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels);
|
|
|
|
const costMult = helpers.number(ctx, "costMult", _costMult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return HScalculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
|
|
|
|
},
|
|
|
|
ramUpgradeCost:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_startingRam, _extraLevels = 1, _costMult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const startingRam = helpers.number(ctx, "startingRam", _startingRam);
|
|
|
|
const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels);
|
|
|
|
const costMult = helpers.number(ctx, "costMult", _costMult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return HScalculateRamUpgradeCost(startingRam, extraLevels, costMult);
|
|
|
|
},
|
|
|
|
coreUpgradeCost:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_startingCore, _extraCores = 1, _costMult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const startingCore = helpers.number(ctx, "startingCore", _startingCore);
|
|
|
|
const extraCores = helpers.number(ctx, "extraCores", _extraCores);
|
|
|
|
const costMult = helpers.number(ctx, "costMult", _costMult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return HScalculateCoreUpgradeCost(startingCore, extraCores, costMult);
|
|
|
|
},
|
|
|
|
cacheUpgradeCost:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_startingCache, _extraCache = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const startingCache = helpers.number(ctx, "startingCache", _startingCache);
|
|
|
|
const extraCache = helpers.number(ctx, "extraCache", _extraCache);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return HScalculateCacheUpgradeCost(startingCache, extraCache);
|
|
|
|
},
|
2022-10-12 14:49:27 +02:00
|
|
|
hashUpgradeCost: (ctx) => (_upgName, _level) => {
|
|
|
|
const upgName = helpers.string(ctx, "upgName", _upgName);
|
|
|
|
const level = helpers.number(ctx, "level", _level);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
const upg = player.hashManager.getUpgrade(upgName);
|
|
|
|
if (!upg) {
|
|
|
|
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid Hash Upgrade: ${upgName}`);
|
|
|
|
}
|
|
|
|
return upg.getCost(level);
|
|
|
|
},
|
2022-05-24 23:29:44 +02:00
|
|
|
hacknetServerCost:
|
2022-10-12 14:49:27 +02:00
|
|
|
(ctx) =>
|
|
|
|
(_n, _mult = 1) => {
|
2022-08-08 19:43:41 +02:00
|
|
|
const n = helpers.number(ctx, "n", _n);
|
|
|
|
const mult = helpers.number(ctx, "mult", _mult);
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return HScalculateServerCost(n, mult);
|
|
|
|
},
|
2022-10-12 14:49:27 +02:00
|
|
|
constants: (ctx) => () => {
|
2022-05-24 23:29:44 +02:00
|
|
|
checkFormulasAccess(ctx);
|
2021-10-14 09:22:02 +02:00
|
|
|
return Object.assign({}, HacknetServerConstants);
|
|
|
|
},
|
|
|
|
},
|
2021-12-09 00:19:30 +01:00
|
|
|
gang: {
|
2022-10-12 14:49:27 +02:00
|
|
|
wantedPenalty: (ctx) => (_gang) => {
|
|
|
|
const gang = helpers.gang(ctx, _gang);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateWantedPenalty(gang);
|
|
|
|
},
|
|
|
|
respectGain: (ctx) => (_gang, _member, _task) => {
|
|
|
|
const gang = helpers.gang(ctx, _gang);
|
|
|
|
const member = helpers.gangMember(ctx, _member);
|
|
|
|
const task = helpers.gangTask(ctx, _task);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateRespectGain(gang, member, task);
|
|
|
|
},
|
|
|
|
wantedLevelGain: (ctx) => (_gang, _member, _task) => {
|
|
|
|
const gang = helpers.gang(ctx, _gang);
|
|
|
|
const member = helpers.gangMember(ctx, _member);
|
|
|
|
const task = helpers.gangTask(ctx, _task);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateWantedLevelGain(gang, member, task);
|
|
|
|
},
|
|
|
|
moneyGain: (ctx) => (_gang, _member, _task) => {
|
|
|
|
const gang = helpers.gang(ctx, _gang);
|
|
|
|
const member = helpers.gangMember(ctx, _member);
|
|
|
|
const task = helpers.gangTask(ctx, _task);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateMoneyGain(gang, member, task);
|
|
|
|
},
|
|
|
|
ascensionPointsGain: (ctx) => (_exp) => {
|
|
|
|
const exp = helpers.number(ctx, "exp", _exp);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateAscensionPointsGain(exp);
|
|
|
|
},
|
|
|
|
ascensionMultiplier: (ctx) => (_points) => {
|
|
|
|
const points = helpers.number(ctx, "points", _points);
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
return calculateAscensionMult(points);
|
|
|
|
},
|
2021-12-09 00:19:30 +01:00
|
|
|
},
|
2022-08-17 20:32:52 +02:00
|
|
|
work: {
|
2022-11-09 13:26:26 +01:00
|
|
|
crimeSuccessChance: (ctx) => (_person, _crimeType) => {
|
2022-11-09 19:46:21 +01:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _person);
|
2022-11-20 14:37:11 +01:00
|
|
|
const crime = findCrime(helpers.string(ctx, "crimeType", _crimeType));
|
|
|
|
if (!crime) throw new Error(`Invalid crime type: ${_crimeType}`);
|
|
|
|
return crime.successRate(person);
|
2022-11-09 13:26:26 +01:00
|
|
|
},
|
2022-11-06 23:27:04 +01:00
|
|
|
crimeGains: (ctx) => (_person, _crimeType) => {
|
2022-11-09 19:46:21 +01:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _person);
|
2022-11-20 14:37:11 +01:00
|
|
|
const crime = findCrime(helpers.string(ctx, "crimeType", _crimeType));
|
|
|
|
if (!crime) throw new Error(`Invalid crime type: ${_crimeType}`);
|
|
|
|
return calculateCrimeWorkStats(person, crime);
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
2022-11-20 14:37:11 +01:00
|
|
|
gymGains: (ctx) => (_person, _classType, _locationName) => {
|
2022-11-09 19:46:21 +01:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
const person = helpers.person(ctx, _person);
|
2022-11-20 14:37:11 +01:00
|
|
|
const classType = findEnumMember(GymType, helpers.string(ctx, "classType", _classType));
|
|
|
|
if (!classType) throw new Error(`Invalid gym training type: ${_classType}`);
|
|
|
|
const locationName = helpers.string(ctx, "locationName", _locationName);
|
|
|
|
if (!checkEnum(LocationName, locationName)) throw new Error(`Invalid location name: ${locationName}`);
|
|
|
|
return calculateClassEarnings(person, classType, locationName);
|
|
|
|
},
|
|
|
|
universityGains: (ctx) => (_person, _classType, _locationName) => {
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
const person = helpers.person(ctx, _person);
|
|
|
|
const classType = findEnumMember(UniversityClassType, helpers.string(ctx, "classType", _classType));
|
|
|
|
if (!classType) throw new Error(`Invalid university class type: ${_classType}`);
|
2022-10-12 14:49:27 +02:00
|
|
|
const locationName = helpers.string(ctx, "locationName", _locationName);
|
2022-11-09 19:46:21 +01:00
|
|
|
if (!checkEnum(LocationName, locationName)) throw new Error(`Invalid location name: ${locationName}`);
|
|
|
|
return calculateClassEarnings(person, classType, locationName);
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
|
|
|
factionGains: (ctx) => (_player, _workType, _favor) => {
|
2022-11-09 19:46:21 +01:00
|
|
|
checkFormulasAccess(ctx);
|
2022-11-09 13:26:26 +01:00
|
|
|
const player = helpers.person(ctx, _player);
|
2022-11-20 14:37:11 +01:00
|
|
|
const workType = findEnumMember(FactionWorkType, helpers.string(ctx, "_workType", _workType));
|
|
|
|
if (!workType) throw new Error(`Invalid faction work type: ${_workType}`);
|
2022-10-12 14:49:27 +02:00
|
|
|
const favor = helpers.number(ctx, "favor", _favor);
|
|
|
|
const exp = calculateFactionExp(player, workType);
|
|
|
|
const rep = calculateFactionRep(player, workType, favor);
|
|
|
|
exp.reputation = rep;
|
|
|
|
return exp;
|
|
|
|
},
|
2022-11-09 19:46:21 +01:00
|
|
|
companyGains: (ctx) => (_person, _companyName, _positionName, _favor) => {
|
|
|
|
checkFormulasAccess(ctx);
|
|
|
|
const person = helpers.person(ctx, _person);
|
2022-12-30 02:28:53 +01:00
|
|
|
const positionName = findEnumMember(JobName, helpers.string(ctx, "_positionName", _positionName));
|
2022-11-20 14:37:11 +01:00
|
|
|
if (!positionName) throw new Error(`Invalid company position: ${_positionName}`);
|
2022-11-09 19:46:21 +01:00
|
|
|
const position = CompanyPositions[positionName];
|
2022-11-06 23:27:04 +01:00
|
|
|
const companyName = helpers.string(ctx, "_companyName", _companyName);
|
|
|
|
const company = Object.values(Companies).find((c) => c.name === companyName);
|
|
|
|
if (!company) throw new Error(`Invalid company name: ${companyName}`);
|
|
|
|
const favor = helpers.number(ctx, "favor", _favor);
|
2022-11-09 19:46:21 +01:00
|
|
|
return calculateCompanyWorkStats(person, company, position, favor);
|
2022-11-06 23:27:04 +01:00
|
|
|
},
|
2022-08-17 20:32:52 +02:00
|
|
|
},
|
2021-10-14 09:22:02 +02:00
|
|
|
};
|
2022-12-30 02:28:53 +01:00
|
|
|
// Removed undocumented functions added using Object.assign because typescript.
|
|
|
|
// TODO: Remove these at 3.0
|
|
|
|
Object.assign(formulasFunctions.work, {
|
|
|
|
classGains: removedFunction("2.2.0", "formulas.work.universityGains or formulas.work.gymGains"),
|
|
|
|
});
|
|
|
|
return formulasFunctions;
|
2021-10-14 09:22:02 +02:00
|
|
|
}
|