Current Version of Bitburner v2.2.1
Simple first Version of a modified Script capable of simple ‘fire and forget’ earning money via the hacknet after visiting BN9.
Intro – Why is Post-BN9 different?
With the advent of Hashes the cost of upgrades goes way up. Before BN9 it is possible for a system of hacknet-servers to pay for themself in a short amount of time. After BN9 that may takes ages, so we want to limit the amount we spent up to a certain point.
I have enabled a ‘first run’ system in which the script takes the hacknet-servers to a certain point. At the moment it is on the requirements for the ‘Netburner-Faction’ if the hacking level is also high enough. During that ‘first run’ we also sell hashes for money in order to not need to wait for the cache to run full.
After the ‘first run’ has passed we go into maintenance mode. The amount of money spent on updates is determined by a MRF factor, adjustable in the script or with an arg[0] during the script call.
I have enabled a ‘first run’ system in which the script takes the hacknet-servers to a certain point. At the moment it is on the requirements for the ‘Netburner-Faction’ if the hacking level is also high enough. During that ‘first run’ we also sell hashes for money in order to not need to wait for the cache to run full.
After the ‘first run’ has passed we go into maintenance mode. The amount of money spent on updates is determined by a MRF factor, adjustable in the script or with an arg[0] during the script call.
Memory Usage
[home ~/]> mem hacknet-manager.js
This script requires 6.70GB of RAM to run for 1 thread(s)
4.00GB | hacknet (ns)
1.60GB | baseCost (misc)
1.00GB | getMoneySources (fn)
100.00MB | getServerMoneyAvailable (fn)
This script requires 6.70GB of RAM to run for 1 thread(s)
4.00GB | hacknet (ns)
1.60GB | baseCost (misc)
1.00GB | getMoneySources (fn)
100.00MB | getServerMoneyAvailable (fn)
Import from ‘myFunction.js’
// function myMoney(ns) : amount of money to always keep and not pay for anything const KEEPSAKE = 1e6; export function myMoney(ns) { let amount = (ns.getServerMoneyAvailable("home") - KEEPSAKE); if (amount > 0) return amount; return 0; }
Main script ‘hacknet-manager.js’ Imports and Constants
/** @param {NS} ns */ // ****************** // imported functions // ****************** import { myMoney } from "./myFunctions.js" export async function main(ns) { // ********* // constants // ********* // Do Not Change const SLEEP_TIME = 1000; // amount of time between updates in ms const MAX_NODES = 20; // only needed for 'done' to end this script const hacknet = ns.hacknet; // Possible to change to suit your needs // During a 'first run' we want only enough to enable joining Netburners-Faction // regardless of money already earned from the hacknet-servers const FR_MAX_NODES = 4; // 4 nodes to keep the investment down const FR_MAX_LEVEL = 25; // 25x4=100 const FR_MAX_RAM = 2; // 2x4= 8 const FR_MAX_CORES = 1; // 1x4= 4 // Change based on the comment possible // change MRF to 0 in order to terminate after the 'first run' // a MRF greater 1 simply invests up to all money available, but ... // that may make the report faulty const DEFAULT_MRF = 0.5; // Money Reinvest Factor between 1 for 100% and 0 for 0% const MRF = (ns.args[0] === undefined ? DEFAULT_MRF : ns.args[0]); // If we only want $ out of the Hacknet-hashes, // increasing the cache is not needed. // true = Upgrading Cache -vs- false = not Upgrading Cache const UPGRADE_CACHE = false;
Main Script ‘hacknet-manager.js’ functions
// ********* // functions // ********* function moneyEarnedHacknet(ns){ return ns.getMoneySources().sinceInstall.hacknet; } function moneySpentHacknet(ns) { return ns.getMoneySources().sinceInstall.hacknet_expenses; } function moneyBalanceHacknet2(ns) { // money balance weighted by the Reinvestment Factor return ((moneyEarnedHacknet(ns) * MRF) + moneySpentHacknet(ns)); } function myMoneyHacknet(ns) { // since we want to limit how much money we spent if (moneyBalanceHacknet2(ns) < 0 ) return 0; if (myMoney(ns) < moneyBalanceHacknet2(ns)) return myMoney(ns); return moneyBalanceHacknet2(ns); } function currentNodes(ns) { return (hacknet.numNodes()); } function currentHashes(ns){ return hacknet.numHashes(); }
Main Script ‘hacknet-manager.js’ report
function moneyBalanceHacknet(ns) { // true count only for the report return (moneyEarnedHacknet(ns) + moneySpentHacknet(ns)); } function totalProductionHashes(ns) { let sumHashes = 0; for (var i = 0; i < currentNodes(ns); i++) { sumHashes += hacknet.getNodeStats(i).totalProduction; } return sumHashes; } function report(ns) { // just a clear summary of things mostly also found elsewhere ns.clearLog(); if (!doneFR(ns)) ns.print("First Run active."); ns.print("Hashes available: # ", ns.nFormat(currentHashes(ns), '0.000a')); ns.print("Possible from Sales: $ ", ns.nFormat(currentHashes(ns)/4*1e6, '0.000a')) ns.print("--------------------------------"); ns.print("Hashes produced: # ", ns.nFormat(totalProductionHashes(ns), '0.000a')); ns.print("Brutto Money earned: $ ", ns.nFormat(moneyEarnedHacknet(ns), '0.000a')); ns.print("Money spent: $ ", ns.nFormat(moneySpentHacknet(ns), '0.000a')); ns.print("Netto Money earned: $ ", ns.nFormat(moneyBalanceHacknet(ns), '0.000a')); ns.print("--------------------------------"); ns.print("------ Waiting for enough ------"); ns.print("Money to ReInvest: $ ", ns.nFormat(myMoneyHacknet(ns), '0.000a')); return; }
Main script ‘hacknet-manager.js’ first run part
function sellHashes(ns){ //Divide hashes by 4 and round down var count = Math.trunc(currentHashes(ns)/4); ns.hacknet.spendHashes("Sell for Money", "mustBeFilled", count); return; } function upgradeFR(ns) { // upgrades during 'first run' // - with the original myMoney // and without upgrading hash-cache capacity for (var i = 0; i < currentNodes(ns); i++) { if ((myMoney(ns) > hacknet.getLevelUpgradeCost(i, 1)) && (hacknet.getNodeStats(i).level < FR_MAX_LEVEL)) { hacknet.upgradeLevel(i, 1); } if ((myMoney(ns) > hacknet.getRamUpgradeCost(i, 1)) && (hacknet.getNodeStats(i).ram < FR_MAX_RAM)) { hacknet.upgradeRam(i, 1); } if ((myMoney(ns) > hacknet.getCoreUpgradeCost(i, 1)) && (hacknet.getNodeStats(i).cores < FR_MAX_CORES)) { hacknet.upgradeCore(i, 1); } } if ((myMoney(ns) > hacknet.getPurchaseNodeCost()) && (currentNodes(ns) < FR_MAX_NODES)) { hacknet.purchaseNode(); } sellHashes(ns); report(ns); return; } function doneFR(ns) { // simple logic to look out if the 'first run' is still currently active let ind = ((FR_MAX_NODES -1) >= currentNodes(ns) ? (currentNodes(ns) -1) : (FR_MAX_NODES -1)); if (currentNodes(ns) == 0) return false; if ((currentNodes(ns) >= ind) && (hacknet.getNodeStats(ind).level >= FR_MAX_LEVEL) && (hacknet.getNodeStats(ind).ram >= FR_MAX_RAM) && (hacknet.getNodeStats(ind).cores >= FR_MAX_CORES)){ return true; } return false; }
Main script ‘hacknet-manager.js’ find cheapest option
function findCULevel(ns) { // finds Cheapest Upgrade Level and returns the index of the node var cl = 0; for (var i = 1; i < currentNodes(ns); i++) { if (hacknet.getLevelUpgradeCost(i, 1) < hacknet.getLevelUpgradeCost(i-1, 1)) cl = i; } return cl; } function findCURam(ns) { // finds Cheapest Upgrade Ram and returns the index of the node var cr = 0; for (var i = 1; i < currentNodes(ns); i++) { if (hacknet.getRamUpgradeCost(i, 1) < hacknet.getRamUpgradeCost(i-1, 1)) cr = i; } return cr; } function findCUCore(ns) { // finds Cheapest Upgrade Core and returns the index of the node var cc = 0; for (var i = 1; i < currentNodes(ns); i++) { if (hacknet.getCoreUpgradeCost(i, 1) < hacknet.getCoreUpgradeCost(i-1, 1)) cc = i; } return cc; } function findCUCache(ns) { // returns the index of the cheapest level-upgrade node var cca = 0; for (var i = 1; i < currentNodes(ns); i++) { if (hacknet.getCacheUpgradeCost(i, 1) < hacknet.getCacheUpgradeCost(i-1, 1)) cca = i; } return cca; } function findCheapest(ns) { // returns a string determining which to upgrade let cheapestObject = "n"; let cheapestPrice = hacknet.getPurchaseNodeCost(); if (hacknet.getLevelUpgradeCost(findCULevel(ns), 1) < cheapestPrice) { cheapestObject = "l"; cheapestPrice = hacknet.getLevelUpgradeCost(findCULevel(ns), 1); } if (hacknet.getRamUpgradeCost(findCURam(ns), 1) < cheapestPrice) { cheapestObject = "r"; cheapestPrice = hacknet.getRamUpgradeCost(findCURam(ns), 1); } if (hacknet.getCoreUpgradeCost(findCUCore(ns), 1) < cheapestPrice) { cheapestObject = "c"; cheapestPrice = hacknet.getCoreUpgradeCost(findCUCore(ns), 1); } if (UPGRADE_CACHE && (hacknet.getCacheUpgradeCost(findCUCache(ns), 1) < cheapestPrice)) { cheapestObject = "ca"; } return cheapestObject; }
Main script ‘hacknet-manager.js’ upgradeReport and done
function upgradeReport(ns) { // returns a printable string as an upgrade to report // would produce errors during 'first run' let urs = ""; let tar2 = findCheapest(ns); if (tar2 == "n") urs = ("Next Upgrade Node for $ " + ns.nFormat(hacknet.getPurchaseNodeCost(), '0.000a')); if (tar2 == "l") urs = ("Next Upgrade Level for $ " + ns.nFormat(hacknet.getLevelUpgradeCost(findCULevel(ns), 1), '0.000a')); if (tar2 == "r") urs = ("Next Upgrade RAM for $ " + ns.nFormat(hacknet.getRamUpgradeCost(findCURam(ns), 1), '0.000a')); if (tar2 == "c") urs = ("Next Upgrade Core for $ " + ns.nFormat(hacknet.getCoreUpgradeCost(findCUCore(ns), 1), '0.000a')); if (tar2 == "ca") urs = ("Next Upgrade Cache for $ " + ns.nFormat(hacknet.getCacheUpgradeCost(findCUCache(ns), 1), '0.000a')); return urs; } function upgrade(ns) { let tar = findCheapest(ns); if (tar == "n" && myMoneyHacknet(ns) > hacknet.getPurchaseNodeCost()) { hacknet.purchaseNode(); } else if (tar == "l" && myMoneyHacknet(ns) > hacknet.getLevelUpgradeCost(findCULevel(ns), 1)) { hacknet.upgradeLevel(findCULevel(ns), 1); } else if (tar == "r" && myMoneyHacknet(ns) > hacknet.getRamUpgradeCost(findCURam(ns), 1)) { hacknet.upgradeRam(findCURam(ns), 1); } else if (tar == "c" && myMoneyHacknet(ns) > hacknet.getCoreUpgradeCost(findCUCore(ns), 1)) { hacknet.upgradeCore(findCUCore(ns), 1); } else if (tar == "ca" && myMoneyHacknet(ns) > hacknet.getCacheUpgradeCost(findCUCache(ns), 1)) { hacknet.upgradeCache(findCUCache(ns), 1); } report(ns); ns.print(upgradeReport(ns)); return; } function done(ns) { if ((hacknet.getPurchaseNodeCost() == Infinity) && (hacknet.getCoreUpgradeCost(MAX_NODES - 1, 1) == Infinity) && (hacknet.getRamUpgradeCost(MAX_NODES - 1, 1) == Infinity) && (hacknet.getLevelUpgradeCost(MAX_NODES - 1, 1) == Infinity) && (hacknet.getCacheUpgradeCost(MAX_NODES - 1, 1) == Infinity)) { // case is the 'normal' way to end this script ns.tprint("All Nodes bought and completly upgraded!"); return true; } else if ((MRF == 0) && (doneFR(ns))) { // case with only enough hacknet capacity for Netburners faction return true; } else return false; // default case - keep running the script }
Main script ‘hacknet-manager.js’ Configuration and Main Loop
// ************* // configuration // ************* ns.tail(); ns.disableLog("sleep"); ns.disableLog("getServerMoneyAvailable"); // ********* // main loop // ********* while(!done(ns)) { if (!doneFR(ns)) upgradeFR(ns); else upgrade(ns); await ns.sleep(SLEEP_TIME); } }
Final Thoughts
The script is not using objects. That would be my biggest planed update. But so far it does exactly what it was build to do. 🙂
Thanks to SilentKnight for his excellent guide, all credits belong to his effort. if this guide helps you, please support and rate it via Steam Community. enjoy the game.
Related Posts:
- Bitburner: Simple Hacknet Manager
- Bitburner: Scan/Nuke/Money Script (Working 2022)
- Bitburner: How to Autocomplete Your Scripts in VSCode
- Bitburner: Unorthodox Automation & In-game Modding
- Bitburner: How to Scan Every Server