From 81fdff9068f1a65bc6ec0f0b48ea26d706886b3f Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sat, 1 May 2021 22:54:48 -0400 Subject: [PATCH 01/23] Revert tutorial servers and add the n00dles server. --- src/Server/data/servers.ts | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/Server/data/servers.ts b/src/Server/data/servers.ts index bd05f97e3..6cef057ce 100644 --- a/src/Server/data/servers.ts +++ b/src/Server/data/servers.ts @@ -1203,10 +1203,10 @@ export const serverMetadata: IServerMetadata[] = [ }, { hackDifficulty: 1, - hostname: "foodnstuff", + hostname: "n00dles", literature: [LiteratureNames.Sector12Crime], - maxRamExponent: 4, - moneyAvailable: 40000, + maxRamExponent: 2, + moneyAvailable: 70000, networkLayer: 1, numOpenPortsRequired: 0, organizationName: LocationName.Sector12FoodNStuff, @@ -1215,26 +1215,39 @@ export const serverMetadata: IServerMetadata[] = [ specialName: LocationName.Sector12FoodNStuff, }, { - hackDifficulty: 3, + hackDifficulty: 10, + hostname: "foodnstuff", + literature: [LiteratureNames.Sector12Crime], + maxRamExponent: 4, + moneyAvailable: 2000000, + networkLayer: 1, + numOpenPortsRequired: 0, + organizationName: LocationName.Sector12FoodNStuff, + requiredHackingSkill: 1, + serverGrowth: 5, + specialName: LocationName.Sector12FoodNStuff, + }, + { + hackDifficulty: 10, hostname: "sigma-cosmetics", maxRamExponent: 4, - moneyAvailable: 70000, + moneyAvailable: 2300000, networkLayer: 1, numOpenPortsRequired: 0, organizationName: "Sigma Cosmetics", requiredHackingSkill: 5, - serverGrowth: 3000, + serverGrowth: 10, }, { - hackDifficulty: 9, + hackDifficulty: 15, hostname: "joesguns", maxRamExponent: 4, - moneyAvailable: 600000, + moneyAvailable: 2500000, networkLayer: 1, numOpenPortsRequired: 0, organizationName: LocationName.Sector12JoesGuns, requiredHackingSkill: 10, - serverGrowth: 500, + serverGrowth: 20, specialName: LocationName.Sector12JoesGuns, }, { @@ -1569,4 +1582,4 @@ export const serverMetadata: IServerMetadata[] = [ serverGrowth: 0, specialName: "w0r1d_d43m0n", }, -]; +]; \ No newline at end of file From 89cdecb05f08f83824c0cdb03d2360fb21cc176e Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sat, 1 May 2021 22:56:28 -0400 Subject: [PATCH 02/23] getBitnodeMultipliers is available inside BN5 --- src/NetscriptFunctions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 6c676b8d2..5816967eb 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -1619,7 +1619,7 @@ function NetscriptFunctions(workerScript) { }, getBitNodeMultipliers: function() { updateDynamicRam("getBitNodeMultipliers", getRamCost("getBitNodeMultipliers")); - if (SourceFileFlags[5] <= 0) { + if (Player.bitNodeN !== 5 && SourceFileFlags[5] <= 0) { throw makeRuntimeErrorMsg("getBitNodeMultipliers", "Requires Source-File 5 to run."); } let copy = Object.assign({}, BitNodeMultipliers); From d2d6453a782b751889270ad86174aef88823ea95 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sat, 1 May 2021 23:23:04 -0400 Subject: [PATCH 03/23] quick b1tflum3 --- src/DevMenu.jsx | 7 ++++++- src/RedPill.js | 12 ++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/DevMenu.jsx b/src/DevMenu.jsx index 98b53fcd1..fd19c44eb 100644 --- a/src/DevMenu.jsx +++ b/src/DevMenu.jsx @@ -135,6 +135,10 @@ class DevMenuComponent extends Component { Player.getHomeComputer().maxRam *= 2; } + quickB1tFlum3() { + hackWorldDaemon(Player.bitNodeN, true, true); + } + b1tflum3() { hackWorldDaemon(Player.bitNodeN, true); } @@ -705,7 +709,8 @@ class DevMenuComponent extends Component {
- + +
diff --git a/src/RedPill.js b/src/RedPill.js index 4a5979b51..6535da60d 100644 --- a/src/RedPill.js +++ b/src/RedPill.js @@ -58,13 +58,17 @@ function writeRedPillLetter(pElem, line, i=0) { } let redPillFlag = false; -function hackWorldDaemon(currentNodeNumber, flume=false) { +function hackWorldDaemon(currentNodeNumber, flume=false, quick=false) { // Clear Red Pill screen first var container = document.getElementById("red-pill-content"); removeChildrenFromElement(container); redPillFlag = true; Engine.loadRedPillContent(); + + if(quick) { + return loadBitVerse(currentNodeNumber, flume, quick); + } return writeRedPillLine("[ERROR] SEMPOOL INVALID").then(function() { return writeRedPillLine("[ERROR] Segmentation Fault"); }).then(function() { @@ -143,7 +147,7 @@ function giveSourceFile(bitNodeNumber) { // is destroyed. Updated every time loadBitVerse() is called let nextSourceFileFlags = []; -function loadBitVerse(destroyedBitNodeNum, flume=false) { +function loadBitVerse(destroyedBitNodeNum, flume=false, quick=false) { // Clear the screen const container = document.getElementById("red-pill-content"); removeChildrenFromElement(container); @@ -221,6 +225,10 @@ function loadBitVerse(destroyedBitNodeNum, flume=false) { }(i)); // Immediate invocation closure } + if(quick) { + return Promise.resolve(true); + } + // Create lore text return writeRedPillLine("Many decades ago, a humanoid extraterrestial species which we call the Enders descended on the Earth...violently").then(function() { return writeRedPillLine("Our species fought back, but it was futile. The Enders had technology far beyond our own..."); From a8d0b6e13d8682a24df1a4059bbd3948a679182c Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sat, 1 May 2021 23:33:44 -0400 Subject: [PATCH 04/23] Tail now accepts PID --- src/Terminal.jsx | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/Terminal.jsx b/src/Terminal.jsx index 20ea87ef4..6fcf04884 100644 --- a/src/Terminal.jsx +++ b/src/Terminal.jsx @@ -53,7 +53,11 @@ import { Player } from "./Player"; import { hackWorldDaemon } from "./RedPill"; import { RunningScript } from "./Script/RunningScript"; import { getRamUsageFromRunningScript } from "./Script/RunningScriptHelpers"; -import { getCurrentEditor, findRunningScript } from "./Script/ScriptHelpers"; +import { + getCurrentEditor, + findRunningScript, + findRunningScriptByPid, +} from "./Script/ScriptHelpers"; import { isScriptFilename } from "./Script/ScriptHelpersTS"; import { AllServers } from "./Server/AllServers"; import { @@ -1406,25 +1410,34 @@ let Terminal = { if (commandArray.length < 2) { postError("Incorrect number of arguments. Usage: tail [script] [arg1] [arg2]..."); } else { - const scriptName = Terminal.getFilepath(commandArray[1]); - if (!isScriptFilename(scriptName)) { - postError("tail can only be called on .script files (filename must end with .script)"); - return; - } + if(typeof commandArray[1] === 'string') { + const scriptName = Terminal.getFilepath(commandArray[1]); + if (!isScriptFilename(scriptName)) { + postError("tail can only be called on .script, .ns, .js files, or by pid"); + return; + } - // Get script arguments - const args = []; - for (let i = 2; i < commandArray.length; ++i) { - args.push(commandArray[i]); - } + // Get script arguments + const args = []; + for (let i = 2; i < commandArray.length; ++i) { + args.push(commandArray[i]); + } - // Check that the script exists on this machine - const runningScript = findRunningScript(scriptName, args, s); - if (runningScript == null) { - postError("No such script exists"); - return; + // Check that the script exists on this machine + const runningScript = findRunningScript(scriptName, args, s); + if (runningScript == null) { + postError("No such script exists"); + return; + } + logBoxCreate(runningScript); + } else { + const runningScript = findRunningScriptByPid(commandArray[1], Player.getCurrentServer()); + if (runningScript == null) { + postError("No such script exists"); + return; + } + logBoxCreate(runningScript); } - logBoxCreate(runningScript); } } catch(e) { Terminal.postThrownError(e); From 7172ef6dae4c9e15fbeb2e97b879143bbf14278b Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sat, 1 May 2021 23:42:52 -0400 Subject: [PATCH 05/23] SF12 now lets player start with Neuroflux --- src/BitNode/BitNode.ts | 3 +-- src/Prestige.js | 5 ++++ src/SourceFile/applySourceFile.ts | 39 ++----------------------------- 3 files changed, 8 insertions(+), 39 deletions(-) diff --git a/src/BitNode/BitNode.ts b/src/BitNode/BitNode.ts index ed86041cc..67adcc3c9 100644 --- a/src/BitNode/BitNode.ts +++ b/src/BitNode/BitNode.ts @@ -236,8 +236,7 @@ BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.", "To iterate is human, to recurse divine.

" + "Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Source-File 12, or " + "if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " + - "of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " + - "In other words, level N of this Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers that decrease)"); + "of Source-File 12 lets you start any BitNodes with NeuroFlux Governor equal to the level of this source file."); // Books: Frontera, Shiner BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON"); diff --git a/src/Prestige.js b/src/Prestige.js index 533d12dde..6c1ce595b 100755 --- a/src/Prestige.js +++ b/src/Prestige.js @@ -340,6 +340,11 @@ function prestigeSourceFile() { updateHashManagerCapacity(); } + if(SourceFileFlags[12] > 0) { + Player.augmentations.push({name: AugmentationNames.NeuroFluxGovernor, level: SourceFileFlags[12]}) + Player.reapplyAllAugmentations(true); + } + // Refresh Main Menu (the 'World' menu, specifically) document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click(); diff --git a/src/SourceFile/applySourceFile.ts b/src/SourceFile/applySourceFile.ts index d6942fd34..03fdadd23 100644 --- a/src/SourceFile/applySourceFile.ts +++ b/src/SourceFile/applySourceFile.ts @@ -141,44 +141,9 @@ export function applySourceFile(srcFile: PlayerOwnedSourceFile): void { Player.company_rep_mult *= incMult; break; } - case 12: { // The Recursion - const inc = Math.pow(1.01, srcFile.lvl); - const dec = Math.pow(0.99, srcFile.lvl); - - Player.hacking_chance_mult *= inc; - Player.hacking_speed_mult *= inc; - Player.hacking_money_mult *= inc; - Player.hacking_grow_mult *= inc; - Player.hacking_mult *= inc; - - Player.strength_mult *= inc; - Player.defense_mult *= inc; - Player.dexterity_mult *= inc; - Player.agility_mult *= inc; - Player.charisma_mult *= inc; - - Player.hacking_exp_mult *= inc; - Player.strength_exp_mult *= inc; - Player.defense_exp_mult *= inc; - Player.dexterity_exp_mult *= inc; - Player.agility_exp_mult *= inc; - Player.charisma_exp_mult *= inc; - - Player.company_rep_mult *= inc; - Player.faction_rep_mult *= inc; - - Player.crime_money_mult *= inc; - Player.crime_success_mult *= inc; - - Player.hacknet_node_money_mult *= inc; - Player.hacknet_node_purchase_cost_mult *= dec; - Player.hacknet_node_ram_cost_mult *= dec; - Player.hacknet_node_core_cost_mult *= dec; - Player.hacknet_node_level_cost_mult *= dec; - - Player.work_money_mult *= inc; + case 12: // The Recursion + // No effects, grants neuroflux. break; - } default: console.error(`Invalid source file number: ${srcFile.n}`); break; From d126b6d8c518457bec5f3b6948ad75e444d96bee Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sat, 1 May 2021 23:44:23 -0400 Subject: [PATCH 06/23] Fix sf minus 1 bad constant --- src/Exploits/applyExploits.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Exploits/applyExploits.ts b/src/Exploits/applyExploits.ts index f1cdfe32d..fede837a4 100644 --- a/src/Exploits/applyExploits.ts +++ b/src/Exploits/applyExploits.ts @@ -4,8 +4,8 @@ export function applyExploit(): void { if (Player.exploits && Player.exploits.length === 0) { return; } - const inc = Math.pow(1.0001, Player.exploits.length); - const dec = Math.pow(0.9999, Player.exploits.length); + const inc = Math.pow(1.001, Player.exploits.length); + const dec = Math.pow(0.999, Player.exploits.length); Player.hacking_chance_mult *= inc; Player.hacking_speed_mult *= inc; From 56ce83cce5d73271ff0a64e457fed1a41431af1f Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 2 May 2021 00:07:04 -0400 Subject: [PATCH 07/23] Fix cashroot not displaying properly --- src/Augmentation/Augmentation.ts | 4 ++-- src/PersonObjects/Resleeving/ResleevingUI.tsx | 7 ++++++- src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts | 14 ++++++++++++-- src/ui/React/AugmentationAccordion.tsx | 11 ++++++++++- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/Augmentation/Augmentation.ts b/src/Augmentation/Augmentation.ts index e1597038f..283265fae 100644 --- a/src/Augmentation/Augmentation.ts +++ b/src/Augmentation/Augmentation.ts @@ -9,7 +9,7 @@ import { Factions } from "../Faction/Factions"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; interface IConstructorParams { - info: string; + info: string | JSX.Element; isSpecial?: boolean; moneyCost: number; name: string; @@ -57,7 +57,7 @@ export class Augmentation { baseRepRequirement = 0; // Description of what this Aug is and what it does - info = ""; + info: string | JSX.Element; // Any Augmentation not immediately available in BitNode-1 is special (e.g. Bladeburner augs) isSpecial = false; diff --git a/src/PersonObjects/Resleeving/ResleevingUI.tsx b/src/PersonObjects/Resleeving/ResleevingUI.tsx index 23b3da192..9dab831a9 100644 --- a/src/PersonObjects/Resleeving/ResleevingUI.tsx +++ b/src/PersonObjects/Resleeving/ResleevingUI.tsx @@ -368,5 +368,10 @@ function updateAugDescription(elems: IResleeveUIElems): void { return; } - elems.augDescription.innerHTML = aug.info; + let innerHTML = aug.info; + if(typeof innerHTML !== 'string') { + innerHTML = renderToStaticMarkup(innerHTML); + } + + elems.augDescription.innerHTML = innerHTML; } diff --git a/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts b/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts index 41604e766..9f0dcf243 100644 --- a/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts +++ b/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts @@ -55,10 +55,15 @@ export function createSleevePurchaseAugsPopup(sleeve: Sleeve, p: IPlayer): void continue; } + let tooltip = aug.info; + if(typeof tooltip !== 'string') { + tooltip = renderToStaticMarkup(tooltip); + } + ownedAugsDiv.appendChild(createElement("div", { class: "gang-owned-upgrade", // Reusing a class from the Gang UI innerText: ownedAug, - tooltip: aug.info, + tooltip: tooltip, })) } popupElems.push(ownedAugsDiv); @@ -83,13 +88,18 @@ export function createSleevePurchaseAugsPopup(sleeve: Sleeve, p: IPlayer): void class: "cmpy-mgmt-upgrade-div", // We'll reuse this CSS class }); + let info = aug.info; + if(typeof info !== 'string') { + info = renderToStaticMarkup(info); + } + div.appendChild(createElement("p", { fontSize: "12px", innerHTML: [ `

${aug.name}


`, `Cost: ${renderToStaticMarkup(Money(aug.startingCost))}

`, - `${aug.info}`, + `${info}`, ].join(" "), padding: "2px", clickListener: () => { diff --git a/src/ui/React/AugmentationAccordion.tsx b/src/ui/React/AugmentationAccordion.tsx index 87ab4ae8f..19eb601f2 100644 --- a/src/ui/React/AugmentationAccordion.tsx +++ b/src/ui/React/AugmentationAccordion.tsx @@ -24,10 +24,19 @@ export function AugmentationAccordion(props: IProps): React.ReactElement { } } + if(typeof props.aug.info === 'string') { + return ( + {displayName}} + panelContent={

} + /> + ) + } + return ( {displayName}} - panelContent={

} + panelContent={

{props.aug.info}

} /> ) } From 5a45e3584d38b9e64a654491db235920e3b7d7c7 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 2 May 2021 01:04:49 -0400 Subject: [PATCH 08/23] Formatted time in netscript hgw display in human time, milliFormat now displays milli sometimes --- src/NetscriptFunctions.js | 6 +++--- src/Terminal.jsx | 8 ++++---- test/StringHelperFunctionsTests.ts | 11 +++++++++++ test/index.js | 1 + utils/StringHelperFunctions.ts | 11 +++++++++-- 5 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 test/StringHelperFunctionsTests.ts diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 5816967eb..e257a6452 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -670,7 +670,7 @@ function NetscriptFunctions(workerScript) { throw makeRuntimeErrorMsg('hack', canHack.msg); } - workerScript.log("hack", `Executing ${ip} in ${hackingTime.toFixed(3)} seconds (t=${threads})`); + workerScript.log("hack", `Executing ${ip} in ${convertTimeMsToTimeElapsedString(hackingTime*1000, true)} (t=${threads})`); return netscriptDelay(hackingTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} @@ -937,7 +937,7 @@ function NetscriptFunctions(workerScript) { } var growTime = calculateGrowTime(server, Player); - workerScript.log("grow", `Executing on '${server.hostname}' in ${formatNumber(growTime, 3)} seconds (t=${threads}).`); + workerScript.log("grow", `Executing on '${server.hostname}' in ${convertTimeMsToTimeElapsedString(growTime*1000, true)} (t=${threads}).`); return netscriptDelay(growTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} const moneyBefore = server.moneyAvailable <= 0 ? 1 : server.moneyAvailable; @@ -988,7 +988,7 @@ function NetscriptFunctions(workerScript) { } var weakenTime = calculateWeakenTime(server, Player); - workerScript.log("weaken", `Executing on '${server.hostname}' in ${formatNumber(weakenTime, 3)} seconds (t=${threads})`); + workerScript.log("weaken", `Executing on '${server.hostname}' in ${convertTimeMsToTimeElapsedString(weakenTime*1000, true)} (t=${threads})`); return netscriptDelay(weakenTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} server.weaken(CONSTANTS.ServerWeakenAmount * threads); diff --git a/src/Terminal.jsx b/src/Terminal.jsx index 6fcf04884..91a670390 100644 --- a/src/Terminal.jsx +++ b/src/Terminal.jsx @@ -583,7 +583,7 @@ let Terminal = { if (!isHacknet) { post("Required hacking skill: " + currServ.requiredHackingSkill); } post("Server security level: " + numeralWrapper.formatServerSecurity(currServ.hackDifficulty)); post("Chance to hack: " + numeralWrapper.formatPercentage(calculateHackingChance(currServ, Player))); - post("Time to hack: " + convertTimeMsToTimeElapsedString(calculateHackingTime(currServ, Player)*1000)); + post("Time to hack: " + convertTimeMsToTimeElapsedString(calculateHackingTime(currServ, Player)*1000, true)); postElement(<>Total money available on server: {Money(currServ.moneyAvailable)}); if (!isHacknet) { post("Required number of open ports for NUKE: " + currServ.numOpenPortsRequired); } @@ -2153,9 +2153,9 @@ let Terminal = { post("Server base security level: " + targetServer.baseDifficulty); post("Server current security level: " + targetServer.hackDifficulty); post("Server growth rate: " + targetServer.serverGrowth); - post(`Netscript hack() execution time: ${convertTimeMsToTimeElapsedString(calculateHackingTime(targetServer, Player)*1000)}`); - post(`Netscript grow() execution time: ${convertTimeMsToTimeElapsedString(calculateGrowTime(targetServer, Player)*1000)}`); - post(`Netscript weaken() execution time: ${convertTimeMsToTimeElapsedString(calculateWeakenTime(targetServer, Player)*1000)}`); + post(`Netscript hack() execution time: ${convertTimeMsToTimeElapsedString(calculateHackingTime(targetServer, Player)*1000, true)}`); + post(`Netscript grow() execution time: ${convertTimeMsToTimeElapsedString(calculateGrowTime(targetServer, Player)*1000, true)}`); + post(`Netscript weaken() execution time: ${convertTimeMsToTimeElapsedString(calculateWeakenTime(targetServer, Player)*1000, true)}`); }; programHandlers[Programs.AutoLink.name] = () => { post("This executable cannot be run."); diff --git a/test/StringHelperFunctionsTests.ts b/test/StringHelperFunctionsTests.ts new file mode 100644 index 000000000..2e45f7845 --- /dev/null +++ b/test/StringHelperFunctionsTests.ts @@ -0,0 +1,11 @@ +import { expect } from "chai"; +import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; + +describe("StringHelperFunctions Tests", function() { + expect(convertTimeMsToTimeElapsedString(1000)).to.equal("1 seconds"); + expect(convertTimeMsToTimeElapsedString(5*60*1000+34*1000)).to.equal("5 minutes 34 seconds"); + expect(convertTimeMsToTimeElapsedString(2*60*60*24*1000+5*60*1000+34*1000)).to.equal("2 days 5 minutes 34 seconds"); + expect(convertTimeMsToTimeElapsedString(2*60*60*24*1000+5*60*1000+34*1000, true)).to.equal("2 days 5 minutes 34.000 seconds"); + expect(convertTimeMsToTimeElapsedString(2*60*60*24*1000+5*60*1000+34*1000+123, true)).to.equal("2 days 5 minutes 34.123 seconds"); + expect(convertTimeMsToTimeElapsedString(2*60*60*24*1000+5*60*1000+34*1000+123.888, true)).to.equal("2 days 5 minutes 34.123 seconds"); +}) \ No newline at end of file diff --git a/test/index.js b/test/index.js index 68045825f..3b95de359 100644 --- a/test/index.js +++ b/test/index.js @@ -1,4 +1,5 @@ export * from "./Netscript/DynamicRamCalculationTests"; export * from "./Netscript/StaticRamCalculationTests"; export * from "./StockMarketTests"; +export * from "./StringHelperFunctionsTests"; export * from "./Terminal/DirectoryTests"; diff --git a/utils/StringHelperFunctions.ts b/utils/StringHelperFunctions.ts index effe284d4..90f80fab5 100644 --- a/utils/StringHelperFunctions.ts +++ b/utils/StringHelperFunctions.ts @@ -13,7 +13,8 @@ Converts a date representing time in milliseconds to a string with the format H e.g. 10000 -> "10 seconds" 120000 -> "2 minutes and 0 seconds" */ -function convertTimeMsToTimeElapsedString(time: number): string { +function convertTimeMsToTimeElapsedString(time: number, showMilli=false): string { + time = Math.floor(time); const millisecondsPerSecond = 1000; const secondPerMinute = 60; const minutesPerHours = 60; @@ -33,7 +34,13 @@ function convertTimeMsToTimeElapsedString(time: number): string { const minutes: number = Math.floor(secTruncHours / secondPerMinute); const secTruncMinutes: number = secTruncHours % secondPerMinute; - const seconds: number = secTruncMinutes; + const milliTruncSec: string = (() => { + let str: string = `${time % millisecondsPerSecond}`; + while(str.length < 3) str = "0"+str; + return str; + })() + + const seconds: string = showMilli ? `${secTruncMinutes}.${milliTruncSec}` : `${secTruncMinutes}`; let res = ""; if (days > 0) {res += `${days} days `; } From f49aff05d7367bceaffc3fa479f90069fc0b24a0 Mon Sep 17 00:00:00 2001 From: Pimvgd Date: Sun, 2 May 2021 23:44:59 +0200 Subject: [PATCH 09/23] typo fixes for blackops --- src/Bladeburner/BlackOperations.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bladeburner/BlackOperations.ts b/src/Bladeburner/BlackOperations.ts index f7ed13fc6..cb75f91d4 100644 --- a/src/Bladeburner/BlackOperations.ts +++ b/src/Bladeburner/BlackOperations.ts @@ -160,7 +160,7 @@ export const BlackOperations: IMap = {}; "technology in Operation K, we've discovered that a small group of " + "MK-VI Synthoids were able to make off with the schematics and design " + "of the technology before the Operation. It is almost a certainty that " + - "these Synthoids are some of the rogue MK-VI ones from the Synthoid Uprising." + + "these Synthoids are some of the rogue MK-VI ones from the Synthoid Uprising.

" + "The goal of Operation Deckard is to hunt down these Synthoids and retire " + "them. I don't need to tell you how critical this mission is.", baseDifficulty:20e3, reqdRank:40e3, @@ -231,7 +231,7 @@ export const BlackOperations: IMap = {}; "means that the supercomputer may be able to reason abstractly " + "and become self-aware.

" + "I do not need to remind you why sentient-level AIs pose a serious " + - "thread to all of mankind.

" + + "threat to all of mankind.

" + "The research for this project is being conducted at one of Fulcrum " + "Technologies secret facilities in Aevum, codenamed 'Alpha Ranch'. " + "Infiltrate the compound, delete and destroy the work, and then find and kill the " + @@ -342,4 +342,4 @@ export const BlackOperations: IMap = {}; weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, }); -})() \ No newline at end of file +})() From a14a694df30d78e671fa313f6dc1103ec6beb1f6 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Mon, 3 May 2021 00:27:12 -0400 Subject: [PATCH 10/23] Fix sleeves not being to work out at volhaven --- src/PersonObjects/Sleeve/Sleeve.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PersonObjects/Sleeve/Sleeve.ts b/src/PersonObjects/Sleeve/Sleeve.ts index 6cd07e3c4..12a34cee4 100644 --- a/src/PersonObjects/Sleeve/Sleeve.ts +++ b/src/PersonObjects/Sleeve/Sleeve.ts @@ -907,7 +907,7 @@ export class Sleeve extends Person { this.currentTaskLocation = LocationName.Sector12PowerhouseGym; costMult = 20; break; - case LocationName.VolhavenMilleniumFitnessGym: + case LocationName.VolhavenMilleniumFitnessGym.toLowerCase(): if (this.city != CityName.Volhaven) { return false; } this.currentTaskLocation = LocationName.VolhavenMilleniumFitnessGym; costMult = 7; From 4eaf68c94018fb6d9728e81f0778b10562a6d96d Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Mon, 3 May 2021 00:37:53 -0400 Subject: [PATCH 11/23] Donation is always visible but locked before favor requirements are fulfilled. --- src/Faction/ui/DonateOption.tsx | 14 ++++++++++++-- src/Faction/ui/Root.tsx | 4 +++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Faction/ui/DonateOption.tsx b/src/Faction/ui/DonateOption.tsx index 9b0c63d48..c7bed8247 100644 --- a/src/Faction/ui/DonateOption.tsx +++ b/src/Faction/ui/DonateOption.tsx @@ -16,6 +16,8 @@ import { dialogBoxCreate } from "../../../utils/DialogBox"; type IProps = { faction: Faction; + disabled: boolean; + favorToDonate: number; p: IPlayer; rerender: () => void; } @@ -36,9 +38,10 @@ export class DonateOption extends React.Component { constructor(props: IProps) { super(props); + this.state = { donateAmt: 0, - status: <>, + status: props.disabled ? <>Unlocked at {props.favorToDonate} favor with {props.faction.name} : <>, } this.calculateRepGain = this.calculateRepGain.bind(this); @@ -90,10 +93,17 @@ export class DonateOption extends React.Component { return (
- +

{this.state.status}

diff --git a/src/Faction/ui/Root.tsx b/src/Faction/ui/Root.tsx index fb9156309..5e8259436 100644 --- a/src/Faction/ui/Root.tsx +++ b/src/Faction/ui/Root.tsx @@ -264,11 +264,13 @@ export class FactionRoot extends React.Component { /> } { - (!isPlayersGang && canDonate) && + !isPlayersGang && }
diff --git a/src/index.html b/src/index.html index d5b147ec9..87f0044e1 100644 --- a/src/index.html +++ b/src/index.html @@ -340,8 +340,8 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %> Would you like to join?

Warning: Joining this faction may prevent you from joining other factions during this run!

- - + + From d422028737f36fa1fa47c357ec22e0254d4fd856 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Mon, 3 May 2021 02:20:31 -0400 Subject: [PATCH 22/23] analyze and ServerProfiler.exe handle hacknet servers better. --- src/Terminal.jsx | 67 +++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/src/Terminal.jsx b/src/Terminal.jsx index 91a670390..46085d14a 100644 --- a/src/Terminal.jsx +++ b/src/Terminal.jsx @@ -575,47 +575,26 @@ let Terminal = { let currServ = Player.getCurrentServer(); const isHacknet = currServ instanceof HacknetServer; post(currServ.hostname + ": "); - post("Organization name: " + currServ.organizationName); - var rootAccess = ""; - if (currServ.hasAdminRights) {rootAccess = "YES";} - else {rootAccess = "NO";} - post("Root Access: " + rootAccess); - if (!isHacknet) { post("Required hacking skill: " + currServ.requiredHackingSkill); } - post("Server security level: " + numeralWrapper.formatServerSecurity(currServ.hackDifficulty)); - post("Chance to hack: " + numeralWrapper.formatPercentage(calculateHackingChance(currServ, Player))); - post("Time to hack: " + convertTimeMsToTimeElapsedString(calculateHackingTime(currServ, Player)*1000, true)); - postElement(<>Total money available on server: {Money(currServ.moneyAvailable)}); - if (!isHacknet) { post("Required number of open ports for NUKE: " + currServ.numOpenPortsRequired); } - - if (currServ.sshPortOpen) { - post("SSH port: Open") - } else { - post("SSH port: Closed") - } - - if (currServ.ftpPortOpen) { - post("FTP port: Open") - } else { - post("FTP port: Closed") - } - - if (currServ.smtpPortOpen) { - post("SMTP port: Open") - } else { - post("SMTP port: Closed") - } - - if (currServ.httpPortOpen) { - post("HTTP port: Open") - } else { - post("HTTP port: Closed") - } - - if (currServ.sqlPortOpen) { - post("SQL port: Open") - } else { - post("SQL port: Closed") - } + const org = currServ.organizationName + post("Organization name: " + (!isHacknet ? org : "Player")); + const admin = currServ.hasAdminRights; + post("Root Access: " + (!isHacknet ? "YES" : "NO")); + const hackingSkill = currServ.requiredHackingSkill + post("Required hacking skill: " + (!isHacknet ? hackingSkill : "N/A")); + const security = currServ.hackDifficulty; + post("Server security level: " + (!isHacknet ? numeralWrapper.formatServerSecurity(security) : "N/A")); + const hackingChance = calculateHackingChance(currServ, Player) + post("Chance to hack: " + (!isHacknet ? numeralWrapper.formatPercentage(hackingChance) : "N/A")); + const hackingTime = calculateHackingTime(currServ, Player)*1000; + post("Time to hack: " + (!isHacknet ? convertTimeMsToTimeElapsedString(hackingTime, true) : "N/A")); + postElement(<>Total money available on server: {!isHacknet ? Money(currServ.moneyAvailable) : "N/A"}); + const numPort = currServ.numOpenPortsRequired; + post("Required number of open ports for NUKE: " + (!isHacknet ? numPort : "N/A")); + post("SSH port: "+ (currServ.sshPortOpen ? "Open" : "Closed")) + post("FTP port: "+ (currServ.ftpPortOpen ? "Open" : "Closed")) + post("SMTP port: "+ (currServ.smtpPortOpen ? "Open" : "Closed")) + post("HTTP port: "+ (currServ.httpPortOpen ? "Open" : "Closed")) + post("SQL port: "+ (currServ.sqlPortOpen ? "Open" : "Closed")) } Terminal.analyzeFlag = false; }, @@ -2149,6 +2128,12 @@ let Terminal = { post("Invalid server IP/hostname"); return; } + + if(targetServer instanceof HacknetServer) { + post(`${Programs.ServerProfiler.name} cannot be run on a Hacknet Server.`); + return + } + post(targetServer.hostname + ":"); post("Server base security level: " + targetServer.baseDifficulty); post("Server current security level: " + targetServer.hackDifficulty); From c421c57e56f77a2a3f62a2e6c5e21c640cd0d97f Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Mon, 3 May 2021 11:58:11 -0400 Subject: [PATCH 23/23] address comments. --- src/NetscriptFunctions.js | 2 +- src/Terminal.jsx | 54 +++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 41d47e99f..74d867f6c 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -1619,7 +1619,7 @@ function NetscriptFunctions(workerScript) { }, getBitNodeMultipliers: function() { updateDynamicRam("getBitNodeMultipliers", getRamCost("getBitNodeMultipliers")); - if (Player.bitNodeN !== 5 && SourceFileFlags[5] <= 0) { + if (SourceFileFlags[5] <= 0 && Player.bitNodeN !== 5) { throw makeRuntimeErrorMsg("getBitNodeMultipliers", "Requires Source-File 5 to run."); } let copy = Object.assign({}, BitNodeMultipliers); diff --git a/src/Terminal.jsx b/src/Terminal.jsx index 46085d14a..501a216bd 100644 --- a/src/Terminal.jsx +++ b/src/Terminal.jsx @@ -1388,35 +1388,33 @@ let Terminal = { try { if (commandArray.length < 2) { postError("Incorrect number of arguments. Usage: tail [script] [arg1] [arg2]..."); - } else { - if(typeof commandArray[1] === 'string') { - const scriptName = Terminal.getFilepath(commandArray[1]); - if (!isScriptFilename(scriptName)) { - postError("tail can only be called on .script, .ns, .js files, or by pid"); - return; - } - - // Get script arguments - const args = []; - for (let i = 2; i < commandArray.length; ++i) { - args.push(commandArray[i]); - } - - // Check that the script exists on this machine - const runningScript = findRunningScript(scriptName, args, s); - if (runningScript == null) { - postError("No such script exists"); - return; - } - logBoxCreate(runningScript); - } else { - const runningScript = findRunningScriptByPid(commandArray[1], Player.getCurrentServer()); - if (runningScript == null) { - postError("No such script exists"); - return; - } - logBoxCreate(runningScript); + } else if(typeof commandArray[1] === 'string') { + const scriptName = Terminal.getFilepath(commandArray[1]); + if (!isScriptFilename(scriptName)) { + postError("tail can only be called on .script, .ns, .js files, or by pid"); + return; } + + // Get script arguments + const args = []; + for (let i = 2; i < commandArray.length; ++i) { + args.push(commandArray[i]); + } + + // Check that the script exists on this machine + const runningScript = findRunningScript(scriptName, args, s); + if (runningScript == null) { + postError("No such script exists"); + return; + } + logBoxCreate(runningScript); + } else { + const runningScript = findRunningScriptByPid(commandArray[1], Player.getCurrentServer()); + if (runningScript == null) { + postError("No such script exists"); + return; + } + logBoxCreate(runningScript); } } catch(e) { Terminal.postThrownError(e);