my-bitburner/src/lib/formula.ts
2023-05-14 18:02:37 +09:00

310 lines
No EOL
10 KiB
TypeScript

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);
}
}