import { NS, Server, Player, BitNodeMultipliers } from "@ns"; const CONSTANTS = { ServerBaseGrowthRate: 1.03, // Unadjusted Growth rate ServerMaxGrowthRate: 1.0035, // Maximum possible growth rate (max rate accounting for server security) ServerFortifyAmount: 0.002, // Amount by which server's security increases when its hacked/grown ServerWeakenAmount: 0.05, // Amount by which server's security decreases when weakened } const DefaultBitNodeMultipliers: BitNodeMultipliers = { HackingLevelMultiplier: 1, StrengthLevelMultiplier: 1, DefenseLevelMultiplier: 1, DexterityLevelMultiplier: 1, AgilityLevelMultiplier: 1, CharismaLevelMultiplier: 1, ServerGrowthRate: 1, ServerMaxMoney: 1, ServerStartingMoney: 1, ServerStartingSecurity: 1, ServerWeakenRate: 1, HomeComputerRamCost: 1, PurchasedServerCost: 1, PurchasedServerSoftcap: 1, PurchasedServerLimit: 1, PurchasedServerMaxRam: 1, CompanyWorkMoney: 1, CrimeMoney: 1, HacknetNodeMoney: 1, ManualHackMoney: 1, ScriptHackMoney: 1, ScriptHackMoneyGain: 1, CodingContractMoney: 1, ClassGymExpGain: 1, CompanyWorkExpGain: 1, CrimeExpGain: 1, FactionWorkExpGain: 1, HackExpGain: 1, FactionPassiveRepGain: 1, FactionWorkRepGain: 1, RepToDonateToFaction: 1, AugmentationMoneyCost: 1, AugmentationRepCost: 1, InfiltrationMoney: 1, InfiltrationRep: 1, FourSigmaMarketDataCost: 1, FourSigmaMarketDataApiCost: 1, CorporationValuation: 1, CorporationSoftcap: 1, BladeburnerRank: 1, BladeburnerSkillCost: 1, GangSoftcap: 1, //GangUniqueAugs: 1, DaedalusAugsRequirement: 30, StaneksGiftPowerMultiplier: 1, StaneksGiftExtraSize: 0, WorldDaemonDifficulty: 1, }; export function calculateIntelligenceBonus(intelligence: number, weight = 1): number { return 1 + (weight * Math.pow(intelligence, 0.8)) / 600; } export function calculateServerGrowth(server: Server, threads: number, p: Player, cores = 1, bit: BitNodeMultipliers = DefaultBitNodeMultipliers): number { 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; if (adjGrowthRate > CONSTANTS.ServerMaxGrowthRate) { adjGrowthRate = CONSTANTS.ServerMaxGrowthRate; } //Calculate adjusted server growth rate based on parameters const serverGrowthPercentage = server.serverGrowth / 100; const numServerGrowthCyclesAdjusted = numServerGrowthCycles * serverGrowthPercentage * bit.ServerGrowthRate; //Apply serverGrowth for the calculated number of growth cycles const coreBonus = 1 + (cores - 1) / 16; return Math.pow(adjGrowthRate, numServerGrowthCyclesAdjusted * p.mults.hacking_grow * coreBonus); } /** * Returns the chance the player has to successfully hack a server */ export function calculateHackingChance(server: Server, player: Player): number { const hackFactor = 1.75; const difficultyMult = (100 - server.hackDifficulty) / 100; const skillMult = hackFactor * player.skills.hacking; const skillChance = (skillMult - server.requiredHackingSkill) / skillMult; const chance = skillChance * difficultyMult * player.mults.hacking_chance * calculateIntelligenceBonus(player.skills.intelligence, 1); if (chance > 1) { return 1; } if (chance < 0) { return 0; } return chance; } /** * Returns the amount of hacking experience the player will gain upon * successfully hacking a server */ export function calculateHackingExpGain(server: Server, player: Player, bit: BitNodeMultipliers = DefaultBitNodeMultipliers): number { const baseExpGain = 3; const diffFactor = 0.3; if (server.baseDifficulty == null) { server.baseDifficulty = server.hackDifficulty; } let expGain = baseExpGain; expGain += server.baseDifficulty * diffFactor; return expGain * player.mults.hacking_exp * bit.HackExpGain; } /** * 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, player: Player, bit: BitNodeMultipliers = DefaultBitNodeMultipliers): number { // Adjust if needed for balancing. This is the divisor for the final calculation const balanceFactor = 240; const difficultyMult = (100 - server.hackDifficulty) / 100; const skillMult = (player.skills.hacking - (server.requiredHackingSkill - 1)) / player.skills.hacking; const percentMoneyHacked = (difficultyMult * skillMult * player.mults.hacking_money * bit.ScriptHackMoney) / balanceFactor; if (percentMoneyHacked < 0) { return 0; } if (percentMoneyHacked > 1) { return 1; } return percentMoneyHacked; } /** * Returns time it takes to complete a hack on a server, in seconds */ export function calculateHackingTime(server: Server, player: Player): number { const difficultyMult = server.requiredHackingSkill * server.hackDifficulty; const baseDiff = 500; const baseSkill = 50; const diffFactor = 2.5; let skillFactor = diffFactor * difficultyMult + baseDiff; // tslint:disable-next-line skillFactor /= player.skills.hacking + baseSkill; const hackTimeMultiplier = 5; const hackingTime = (hackTimeMultiplier * skillFactor) / (player.mults.hacking_speed * calculateIntelligenceBonus(player.skills.intelligence, 1)); return hackingTime; } /** * Returns time it takes to complete a grow operation on a server, in seconds */ export function calculateGrowTime(server: Server, player: Player): number { const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2 return growTimeMultiplier * calculateHackingTime(server, player); } /** * Returns time it takes to complete a weaken operation on a server, in seconds */ export function calculateWeakenTime(server: Server, player: Player): number { const weakenTimeMultiplier = 4; // Relative to hacking time return weakenTimeMultiplier * calculateHackingTime(server, player); } export function canBeAccessBitNode(ns: NS): boolean { try { ns.getBitNodeMultipliers(); return true; } catch (error) { return false; } } export function getBitNodeMultipliersSafe(ns: NS): BitNodeMultipliers { const fnName = "getBitNodeMultipliers"; const isEnabled = ns.isLogEnabled(fnName); ns.disableLog("disableLog"); ns.disableLog("enableLog"); ns.disableLog("getBitNodeMultipliers"); try { return ns.getBitNodeMultipliers(); } catch (error) { if (typeof error === "string") { return DefaultBitNodeMultipliers; } throw error; } finally { if (isEnabled) { ns.enableLog("getBitNodeMultipliers"); } } } export class FormulaHelper { ns: NS; constructor(ns: NS) { this.ns = ns; } calculateWeakenThreadCountToTargetSecurity(targetSecurity: number, curSecurity: number, cores = 1): number { if(curSecurity < targetSecurity) { return 0; } const k = curSecurity - targetSecurity; const c = this.ns.weakenAnalyze(1, cores); return k / c; } calculateGrowThreadCount(hostname: string, currentMoney: number, targetMoney: number, cores = 1): number { const g = this.ns.growthAnalyze(hostname, targetMoney / currentMoney, cores); return g; } calculateHackSecurity(nThread: number): number { const ServerFortifyAmount = 0.002; return ServerFortifyAmount * nThread; } calculuateGrowthSecurity(nThread: number, cores = 1): number { const ServerWeakenAmount = 0.004; const mul = getBitNodeMultipliersSafe(this.ns); const coreBonus = 1 + (cores - 1) / 16; return ServerWeakenAmount * nThread * coreBonus * mul.ServerWeakenRate; } /** * Returns time it takes to complete a weaken operation on a server, in milliseconds * @param server * @returns milliseconds to complete a weaken operation */ calculateWeakenTime(server: Server): number { const player = this.ns.getPlayer(); return calculateWeakenTime(server, player) * 1000; } /** * Returns time it takes to complete a grow operation on a server, in milliseconds * @param server * @returns milliseconds to complete a grow operation */ calculateGrowTime(server: Server): number { const player = this.ns.getPlayer(); return calculateGrowTime(server, player) * 1000; } /** * Returns time it takes to complete a hacking operation on a server, in milliseconds * @param server * @returns milliseconds to complete a hacking operation */ calculateHackingTime(server: Server): number { const player = this.ns.getPlayer(); return calculateHackingTime(server, player) * 1000; } /** * Hack * @param server server to get * @returns percent of earned money (0~1 value) * @example * ```ts * calculatePercentMoneyHacked(server) //0.2 mean 20% * ``` */ calculatePercentMoneyHacked(server: Server): number { const player = this.ns.getPlayer(); const bit = getBitNodeMultipliersSafe(this.ns); return calculatePercentMoneyHacked(server, player, bit); } calculateServerGrowth(server: Server, thread: number, cores = 1): number { const player = this.ns.getPlayer(); const bit = getBitNodeMultipliersSafe(this.ns); return calculateServerGrowth(server, thread, player, cores, bit); } calculateHackingChance(server: Server): number { const player = this.ns.getPlayer(); return calculateHackingChance(server, player); } calculateHackingExpGain(server: Server): number{ const player = this.ns.getPlayer(); const bit = getBitNodeMultipliersSafe(this.ns); return calculateHackingExpGain(server,player,bit); } }