diff --git a/ascend.js b/ascend.js index 7a8a8612..a5f32482 100644 --- a/ascend.js +++ b/ascend.js @@ -1,6 +1,6 @@ import { log, getConfiguration, getFilePath, runCommand, waitForProcessToComplete, getNsDataThroughFile, - getActiveSourceFiles, getStockSymbols + getActiveSourceFiles, getStockSymbols, getCompatibleApi } from './helpers.js' const argsSchema = [ @@ -53,7 +53,7 @@ export async function main(ns) { ns.run(getFilePath('spend-hacknet-hashes.js'), 1, '--liquidate'); // If we do not have tix api access, we cannot automate checking on or selling stocks, so skip this - const hasTixApiAccess = await getNsDataThroughFile(ns, 'ns.stock.hasTIXAPIAccess()'); + const hasTixApiAccess = await getNsDataThroughFile(ns, `ns.stock.${getCompatibleApi(ns, "hasTixApiAccess")}()`); if (hasTixApiAccess) { const stkSymbols = await getStockSymbols(ns); const countOwnedStocks = async () => await getNsDataThroughFile(ns, `ns.args.map(sym => ns.stock.getPosition(sym))` + diff --git a/autopilot.js b/autopilot.js index 3b55af49..33fb1635 100644 --- a/autopilot.js +++ b/autopilot.js @@ -1,7 +1,7 @@ import { log, getFilePath, getConfiguration, instanceCount, getNsDataThroughFile, runCommand, waitForProcessToComplete, getActiveSourceFiles, tryGetBitNodeMultipliers, getStocksValue, unEscapeArrayArgs, - formatMoney, formatDuration, formatNumber, getErrorInfo, tail, jsonReplacer + formatMoney, formatDuration, formatNumber, getErrorInfo, tail, jsonReplacer, getCompatibleApi } from './helpers.js' const argsSchema = [ // The set of all command line arguments @@ -874,7 +874,11 @@ export async function main(ns) { // If we are in Daedalus, and we do not yet have enough favour to unlock rep donations with Daedalus, // but we DO have enough rep to earn that favor on our next restart, trigger an install immediately (need at least 1 aug) // (doesn't apply in BN8, since we can immediately donate to all factions) - if (player.factions.includes("Daedalus") && bitNodeMults.RepToDonateToFaction !== 0 && ns.read("/Temp/Daedalus-donation-rep-attained.txt")) { + if ( + player.factions.includes("Daedalus") && + bitNodeMults[getCompatibleApi(ns, "FavorToDonateToFaction")] !== 0 && + ns.read("/Temp/Daedalus-donation-rep-attained.txt") + ) { shouldReset = true; resetStatus = `We have enough reputation with Daedalus to unlock donations on our next reset.\n${resetStatus}`; if (totalCost == 0) totalCost = 1; // Hack, logic below expects some non-zero reserve in preparation for ascending. @@ -975,7 +979,7 @@ export async function main(ns) { if (await checkIfGrafting(ns)) return true; // Are we close to being able to afford 4S TIX data? - if (!options['disable-wait-for-4s'] && !(await getNsDataThroughFile(ns, `ns.stock.has4SDataTIXAPI()`))) { + if (!options['disable-wait-for-4s'] && !(await getNsDataThroughFile(ns, `ns.stock.${getCompatibleApi(ns, "has4SDataTixApi")}()`))) { const totalWorth = player.money + await getStocksValue(ns); const has4S = await getNsDataThroughFile(ns, `ns.stock.has4SData()`); const totalCost = 25E9 * bitNodeMults.FourSigmaMarketDataApiCost + diff --git a/daemon.js b/daemon.js index 09f4bae0..f7d86889 100644 --- a/daemon.js +++ b/daemon.js @@ -3,7 +3,7 @@ import { hashCode, disableLogs, log, getFilePath, getConfiguration, getNsDataThroughFile_Custom, runCommand_Custom, waitForProcessToComplete_Custom, tryGetBitNodeMultipliers_Custom, getActiveSourceFiles_Custom, - getFnRunViaNsExec, tail, autoRetry, getErrorInfo + getFnRunViaNsExec, tail, autoRetry, getErrorInfo, getCompatibleApi } from './helpers.js' // daemon.js has histocially been the central orchestrator of almost every script in the game. @@ -1057,8 +1057,8 @@ export async function main(ns) { // Hack: Below concerns aren't related to "server data", but are things we also wish to refresh just once in a while // Determine whether we have purchased stock API accesses yet (affects reserving and attempts to manipulate stock markets) - haveTixApi = haveTixApi || await getNsDataThroughFile(ns, `ns.stock.hasTIXAPIAccess()`); - have4sApi = have4sApi || await getNsDataThroughFile(ns, `ns.stock.has4SDataTIXAPI()`); + haveTixApi = haveTixApi || await getNsDataThroughFile(ns, `ns.stock.${getCompatibleApi(ns, "hasTixApiAccess")}()`); + have4sApi = have4sApi || await getNsDataThroughFile(ns, `ns.stock.${getCompatibleApi(ns, "has4SDataTixApi")}()`); // If required, determine the current terminal server (used when intelligence farming) if (options.i) currentTerminalServer = getServerByName(await getNsDataThroughFile(ns, 'ns.singularity.getCurrentServer()')); diff --git a/gangs.js b/gangs.js index ac574dcf..bfbb31c7 100644 --- a/gangs.js +++ b/gangs.js @@ -1,6 +1,6 @@ import { log, getConfiguration, instanceCount, getNsDataThroughFile, getActiveSourceFiles, runCommand, tryGetBitNodeMultipliers, - formatMoney, formatNumberShort, formatDuration + formatMoney, formatNumberShort, formatDuration, getCompatibleApi } from './helpers.js' // Global config @@ -437,7 +437,7 @@ async function tryUpgradeMembers(ns, dictMembers) { let augBudget = Math.min(maxBudget, (options['augmentations-budget'] || defaultMaxSpendPerTickPermanentEquipment)) * homeMoney; // Hack: Default aug budget is cut by 1/100 in a few situations (TODO: Add more, like when BitnodeMults are such that gang income is severely nerfed) if (!is4sBought) - is4sBought = await getNsDataThroughFile(ns, 'ns.stock.has4SDataTIXAPI()'); + is4sBought = await getNsDataThroughFile(ns, `ns.stock.${getCompatibleApi(ns, "has4SDataTixApi")}()`); if (!is4sBought || resetInfo.currentNode === 8) { budget /= 100; augBudget /= 100; diff --git a/go.js b/go.js index b202b36f..5ad49cde 100644 --- a/go.js +++ b/go.js @@ -11,7 +11,7 @@ */ import { - getConfiguration, instanceCount, log, getErrorInfo, getActiveSourceFiles, getNsDataThroughFile, tail + getConfiguration, instanceCount, log, getErrorInfo, getActiveSourceFiles, getNsDataThroughFile, formatTime } from './helpers.js' const argsSchema = [ @@ -1306,7 +1306,7 @@ export async function main(ns) { ns.printf("%s", attack.msg) const results = await go_makeMove(ns, x, y); let END = performance.now() - if (logtime) ns.printf("Time: Me: %s Them: %s", ns.tFormat(mid - START, true), ns.tFormat(END - mid, true)) + if (logtime) ns.printf("Time: Me: %s Them: %s", formatTime(ns, mid - START, true), formatTime(ns, END - mid, true)) START = performance.now() return results } @@ -1323,7 +1323,7 @@ export async function main(ns) { const results = await go_cheat_playTwoMoves(ns, s1x, s1y, s2x, s2y) ns.printf("%s Chance: %.2f%% Result: %s", attack.msg, chance * 100, results.type); let END = performance.now() - if (logtime) ns.printf("Time: Me: %s Them: %s", ns.tFormat(mid - START, true), ns.tFormat(END - mid, true)) + if (logtime) ns.printf("Time: Me: %s Them: %s", formatTime(ns, mid - START, true), formatTime(ns, END - mid, true)) START = performance.now() return results } diff --git a/helpers.js b/helpers.js index 6eed0e85..37859c0d 100644 --- a/helpers.js +++ b/helpers.js @@ -662,7 +662,13 @@ export async function getHardCodedBitNodeMultipliers(ns, fnGetNsDataThroughFile, PurchasedServerSoftcap: /* */[1, 1.3, 1.3, 1.2, 1.2, 2, 2, 4, 1, 1.1, 2, 1, 1.6, 1], PurchasedServerLimit: /* */[1, 1, 1, 1, 1, 1, 1, 1, 0, 0.6, 1, 1, 1, 1], PurchasedServerMaxRam: /* */[1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 1, 1, 1, 1], + // TODO: v3.0.0 + /** + * RepToDonateToFaction and FavorToDonateToFaction have the same value. RepToDonateToFaction was renamed to + * FavorToDonateToFaction in v3.0.0. + */ RepToDonateToFaction: /* */[1, 1, 0.5, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], + FavorToDonateToFaction: /* */[1, 1, 0.5, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], ScriptHackMoney: /* */[1, 1, 0.2, 0.2, 0.15, 0.75, 0.5, 0.3, 0.1, 0.5, 1, 1, 0.2, 0.3], ScriptHackMoneyGain: /* */[1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], ServerGrowthRate: /* */[1, 0.8, 0.2, 1, 1, 1, 1, 1, 1, 1, 0.2, 1, 1, 1], @@ -889,4 +895,36 @@ export function tail(ns, processId = undefined) { ns.ui.moveTail(offsetPct * (width * 0.25 - 300) + 250, offsetPct * (height * 0.75 - 100) + 50, processId); tailedPids.push(processId); ns.write(tailFile, JSON.stringify(tailedPids), 'w'); +} + +// TODO: v3.0.0 +function isV3(ns) { + return ns.ui.getGameInfo().versionNumber >= 44; +} + +export function formatTime(ns, milliseconds, milliPrecision) { + if (isV3(ns)) { + return ns.ui.time(milliseconds, milliPrecision); + } + return ns.tFormat(milliseconds, milliPrecision); +} + +export function getCompatibleApi(ns, latestApi) { + if (isV3(ns)) { + return latestApi; + } + // Return v2 APIs + switch (latestApi) { + case "hasWseAccount": + return "hasWSEAccount"; + case "hasTixApiAccess": + return "hasTIXAPIAccess"; + case "has4SDataTixApi": + return "has4SDataTIXAPI"; + case "FavorToDonateToFaction": + return "RepToDonateToFaction"; + } + const errorMessage = `Unknown API: ${latestApi}`; + ns.tprint(`\u001b[31m${errorMessage}`); + throw new Error(errorMessage); } \ No newline at end of file diff --git a/sleeve.js b/sleeve.js index fe243955..803cc1b8 100644 --- a/sleeve.js +++ b/sleeve.js @@ -302,7 +302,7 @@ async function pickSleeveTask(ns, playerInfo, playerWorkInfo, i, sleeve, canTrai } // If gangs are available, prioritize homicide until we've got the requisite -54K karma to unlock them if (!playerInGang && !options['disable-gang-homicide-priority'] && (2 in ownedSourceFiles) && ns.heart.break() > -54000) - return await crimeTask(ns, 'homicide', i, sleeve, 'we want gang karma'); // Ignore chance - even a failed homicide generates more Karma than every other crime + return await crimeTask(ns, 'Homicide', i, sleeve, 'we want gang karma'); // Ignore chance - even a failed homicide generates more Karma than every other crime // If the player is in bladeburner, and has already unlocked gangs with Karma, generate contracts and operations if (playerInBladeburner) { // Hack: Without paying much attention to what's happening in bladeburner, pre-assign a variety of tasks by sleeve index diff --git a/stockmaster.js b/stockmaster.js index ad72884b..01099bab 100644 --- a/stockmaster.js +++ b/stockmaster.js @@ -1,6 +1,6 @@ import { instanceCount, getConfiguration, getNsDataThroughFile, runCommand, getActiveSourceFiles, tryGetBitNodeMultipliers, - formatMoney, formatNumberShort, formatDuration, getStockSymbols + formatMoney, formatNumberShort, formatDuration, getStockSymbols, getCompatibleApi } from './helpers.js' let disableShorts = false; @@ -74,7 +74,7 @@ export async function main(ns) { // If given the "liquidate" command, try to kill any versions of this script trading in stocks // NOTE: We must do this immediately before we start resetting / overwriting global state below (which is shared between script instances) - const hasTixApiAccess = await getNsDataThroughFile(ns, 'ns.stock.hasTIXAPIAccess()'); + const hasTixApiAccess = await getNsDataThroughFile(ns, `ns.stock.${getCompatibleApi(ns, "hasTixApiAccess")}()`); if (runOptions.l || runOptions.liquidate) { if (!hasTixApiAccess) return log(ns, 'ERROR: Cannot liquidate stocks because we do not have Tix Api Access', true, 'error'); log(ns, 'INFO: Killing any other stockmaster processes...', false, 'info'); @@ -156,7 +156,7 @@ export async function main(ns) { const playerStats = await getPlayerInfo(ns); const reserve = options['reserve'] != null ? options['reserve'] : Number(ns.read("reserve.txt") || 0); // Check whether we have 4s access yes (once we do, we can stop checking) - if (pre4s) pre4s = !(await checkAccess(ns, 'has4SDataTIXAPI')); + if (pre4s) pre4s = !(await checkAccess(ns, getCompatibleApi(ns, "has4SDataTixApi"))); const holdings = await refresh(ns, !pre4s, allStocks, myStocks); // Returns total stock value const corpus = holdings + playerStats.money; // Corpus means total stocks + cash const maxHoldings = (1 - fracH) * corpus; // The largest value of stock we could hold without violiating fracH (Fraction to keep as cash) @@ -554,7 +554,7 @@ async function liquidate(ns) { /** @param {NS} ns **/ /** @param {Player} playerStats **/ async function tryGet4SApi(ns, playerStats, budget) { - if (await checkAccess(ns, 'has4SDataTIXAPI')) return false; // Only return true if we just bought it + if (await checkAccess(ns, getCompatibleApi(ns, "has4SDataTixApi"))) return false; // Only return true if we just bought it const cost4sData = 1E9 * bitNodeMults.FourSigmaMarketDataCost; const cost4sApi = 25E9 * bitNodeMults.FourSigmaMarketDataApiCost; const has4S = await checkAccess(ns, 'has4SData'); @@ -582,7 +582,7 @@ async function tryGet4SApi(ns, playerStats, budget) { } /** @param {NS} ns - * @param {"hasWSEAccount"|"hasTIXAPIAccess"|"has4SData"|"has4SDataTIXAPI"} stockFn + * @param {"hasWseAccount"|"hasTixApiAccess"|"has4SData"|"has4SDataTixApi"} stockFn * Helper to check for one of the stock access functions */ async function checkAccess(ns, stockFn) { return await getNsDataThroughFile(ns, `ns.stock.${stockFn}()`) @@ -599,10 +599,10 @@ async function tryBuy(ns, stockFn) { * @param {number} budget - The amount we are willing to spend on WSE and API access * Tries to purchase access to the stock market **/ async function tryGetStockMarketAccess(ns, budget) { - if (await checkAccess(ns, 'hasTIXAPIAccess')) return true; // Already have access + if (await checkAccess(ns, getCompatibleApi(ns, "hasTixApiAccess"))) return true; // Already have access const costWseAccount = 200E6; const costTixApi = 5E9; - const hasWSE = await checkAccess(ns, 'hasWSEAccount'); + const hasWSE = await checkAccess(ns, getCompatibleApi(ns, "hasWseAccount")); const totalCost = (hasWSE ? 0 : costWseAccount) + costTixApi; if (totalCost > budget) return false; if (!hasWSE) {