diff --git a/doc/source/conf.py b/doc/source/conf.py index 22d8d56b0..46634b60b 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -64,9 +64,9 @@ documentation_title = '{0} Documentation'.format(project) # built documents. # # The short X.Y version. -version = '0.43' +version = '0.44' # The full version, including alpha/beta/rc tags. -release = '0.43.0' +release = '0.44.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/source/guidesandtips.rst b/doc/source/guidesandtips.rst index d01e67cdd..c2f17f202 100644 --- a/doc/source/guidesandtips.rst +++ b/doc/source/guidesandtips.rst @@ -1,9 +1,11 @@ Guides & Tips ============= +Getting Started Guide for Intermediate Programmers +What BitNode should I do? +Beginners FAQ + .. toctree:: :maxdepth: 3 - Getting Started Guide for Beginner Programmers - Getting Started Guide for Intermediate Programmers - What BitNode should I do? + Getting Started Guide for Beginner Programmers diff --git a/doc/source/guidesandtips/gettingstartedguideforbeginnerprogrammers.rst b/doc/source/guidesandtips/gettingstartedguideforbeginnerprogrammers.rst new file mode 100644 index 000000000..7d17e78b5 --- /dev/null +++ b/doc/source/guidesandtips/gettingstartedguideforbeginnerprogrammers.rst @@ -0,0 +1,47 @@ +Getting Started Guide for Beginner Programmers +============================================== + +.. note:: Note that the scripts and strategies given in this guide aren't necessarily + optimal. They're just meant to introduce you to the game and help you get + started. + +This is an introductory guide to getting started with Bitburner. It is not meant to be a +comprehensive guide for the entire game, only the early stages. If you are confused +or overwhelmed by the game, especially the programming and scripting aspects, this +guide is perfect for you! + +Note that this guide is tailored towards those with minimal programming experience. + +Introduction +------------ +Bitburner is a cyberpunk-themed incremental RPG. The player progresses by raising +their :ref:`gameplay_stats`, earning money, and :ref:`climbing the corporate ladder `. +Eventually, after reaching certain criteria, the player will begin receiving invitations +from :ref:`gameplay_factions`. Joining these factions and working for them will unlock +:ref:`gameplay_augmentations`. Purchasing and installing Augmentations provide persistent +upgrades and are necessary for progressing in the game. + +The game has a minimal story/quest-line that can be followed to reach the end of the game. +Since this guide is only about getting started with Bitburner, it will not cover the +entire "quest-line". + +First Steps +----------- +I'm going to assume you followed the introductory tutorial when you first began the game. +In this introductory tutorial you created a script called `foodnstuff.script` and ran it +on the `foodnstuff` server. Right now, we'll kill this script. There are two ways +to do this: + +1. You can go to the Terminal and enter:: + + $ kill foodnstuff.script + +2. You can go to the "Active Scripts" page (:ref:`Keyboard shortcut ` Alt + s) and + press the "Kill Script" button for `foodnstuff.script`. + +If you skipped the introductory tutorial, then ignore the part above. Instead, go to the +"Hacknet Nodes" page (:ref:`Keyboard shortcut ` Alt + h) and purchase a +Hacknet Node to start generating some passive income. + +Creating our First Scripts +-------------------------- diff --git a/src/Constants.ts b/src/Constants.ts index 8ef109394..eb36b0b1b 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -510,44 +510,15 @@ export let CONSTANTS: IMap = { LatestUpdate: ` - v0.44.0 - * Bladeburner Changes: - ** Reduced the amount of rank needed to earn a skill point - ** Reduced the effects of the "Reaper" and "Evasive System" skills - ** Increased the effect of the "Hyperdrive" and "Hands of Midas" skills - ** Slightly increased the rate which the skill point cost rises for almost all skills - ** The "Overlock" Skill now has a maximum level of 90 instead of 95 - ** Money earned from Contracts increased by 400% - ** Changed the way population affects success rate. Extreme populations now have less dramatic effects - ** Added two new General Actions: Diplomacy and Hyperbolic Regeneration Chamber - ** Lowered the rep and money cost of the "Blade's Simulacrum" augmentation - ** Significantly decreased the initial amount of Contracts/Operations (the "Contracts/Operations remaining" value) - ** Decreased the rate at which the amount of Contracts/Operations increases over time - ** Decreased the number of successes you need to increase the max level of a Contract/Operation - ** Increased the average number of Synthoid communities each city has - ** Reduced the amount by which a successful raid will decrease the population of a city - ** The "riots" event will now increase the chaos of a city by a greater amount - ** Significantly increased the effect that Agility and Dexterity have on action time + v0.44.1 + * Duplicate Sleeve changes: + ** You can now purchase Augmentations for your Duplicate Sleeves + ** Sleeves are now assigned to Shock Recovery task by default + ** Shock Recovery and Synchronize tasks are now twice as effective - * Added new BitNode multipliers: - ** HomeComputerRamCost - Affects how much it costs to upgrade home computer's RAM - ** DaedalusAugsRequirement - Affects how many Augmentations you need in order to get invited to Daedalus - ** FourSigmaMarketDataCost - Affects how much it costs to unlock the stock market's 4S Market Data - ** FourSigmaMarketDataApiCost - Affects how much it costs to unlock the stock market's 4S Market Data API - - * A few minor changes to BitNode multipliers across the board (mostly for the new multipliers) - * 'The Covenant' now requires 20 total Augmentations to get invited, rather than 30 - * You can now purchase permanent Duplicate Sleeves from 'The Covenant'. This requires Source-File 10, and you must be in BN-10 or after - * You can now track where all of your money comes from in the 'Stats' page - * Increased the money gained from Coding Contracts by 50% - * getCharacterInformation() function now returns the player's HP and max HP - * Bug Fix: You can no longer disconnect the enemy's connections in Hacking Missions - * Bug Fix: Duplicate Sleeve faction reputation gain is now properly affected by faction favor - * Bug Fix: After installing Augmentations, the Terminal display will now correctly show the current server as "home" - * Bug Fix: Fixed an exploit where you could change the duration of timed functions (e.g. hack, weaken) in NetscriptJS - * Bug Fix: You should now properly be able to use the ServerProfile.exe program - * Bug Fix: Prevented exploit that allowed you to accept faction invites programmatically through NetscriptJS - * Bug Fix: Faction invitations for megacorporations should now work properly + * Bug Fix: 'rm' Terminal and Netscript commands now work on non-program files that have '.exe' in the name (by Github user MasonD) + * Bug Fix: The 'Find All Valid Math Expressions' Coding Contract should now properly ignore whitespace in answers + * Bug Fix: The 'Merge Overlapping Intervals' Coding Contract should now properly accept 2D arrays when being attempted through Netscript ` } diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 9b7e6a56a..e2e585616 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -53,9 +53,6 @@ import {StockMarket, StockSymbols, SymbolToStockMap, PositionTypes, placeOrder, cancelOrder} from "./StockMarket/StockMarket"; import { getStockmarket4SDataCost, getStockMarket4STixApiCost } from "./StockMarket/StockMarketCosts"; -import {numeralWrapper} from "./ui/numeralFormat"; -import {post} from "./ui/postToTerminal"; -import { setTimeoutRef } from "./utils/SetTimeoutRef"; import {TextFile, getTextFile, createTextFile} from "./TextFile"; import {unknownBladeburnerActionErrorMessage, @@ -68,8 +65,12 @@ import {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript} from "./NetscriptEvaluator"; import {NetscriptPort} from "./NetscriptPort"; -import Decimal from "decimal.js"; import {Page, routing} from "./ui/navigationTracking"; +import {numeralWrapper} from "./ui/numeralFormat"; +import {post} from "./ui/postToTerminal"; +import { setTimeoutRef } from "./utils/SetTimeoutRef"; +import { is2DArray } from "./utils/helpers/is2DArray"; + import {dialogBoxCreate} from "../utils/DialogBox"; import {isPowerOfTwo} from "../utils/helpers/isPowerOfTwo"; import {arrayToString} from "../utils/helpers/arrayToString"; @@ -4686,7 +4687,20 @@ function NetscriptFunctions(workerScript) { workerScript.log(`ERROR: codingcontract.getData() failed because it could find the specified contract ${fn} on server ${ip}`); return false; } - answer = String(answer); + + // Convert answer to string. If the answer is a 2D array, then we have to + // manually add brackets for the inner arrays + if (is2DArray(answer)) { + let answerComponents = []; + for (let i = 0; i < answer.length; ++i) { + answerComponents.push(["[", answer[i].toString(), "]"].join("")); + } + + answer = answerComponents.join(","); + } else { + answer = String(answer); + } + const serv = safeGetServer(ip, "codingcontract.attempt()"); if (contract.isSolution(answer)) { const reward = Player.gainCodingContractReward(contract.reward, contract.getDifficulty()); diff --git a/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts b/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts index 280b8b37b..3fc5b76a7 100644 --- a/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts +++ b/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts @@ -16,14 +16,9 @@ import { numeralWrapper } from "../../ui/numeralFormat"; import { dialogBoxCreate } from "../../../utils/DialogBox"; -import { clearEventListeners } from "../../../utils/uiHelpers/clearEventListeners"; import { createElement } from "../../../utils/uiHelpers/createElement"; import { createPopup } from "../../../utils/uiHelpers/createPopup"; import { createPopupCloseButton } from "../../../utils/uiHelpers/createPopupCloseButton"; -import { getSelectValue } from "../../../utils/uiHelpers/getSelectData"; -import { removeChildrenFromElement } from "../../../utils/uiHelpers/removeChildrenFromElement"; -import { removeElement } from "../../../utils/uiHelpers/removeElement"; -import { removeElementById } from "../../../utils/uiHelpers/removeElementById"; export function createSleevePurchaseAugsPopup(sleeve: Sleeve, p: IPlayer) { // You can only purchase Augmentations that are actually available from @@ -44,6 +39,8 @@ export function createSleevePurchaseAugsPopup(sleeve: Sleeve, p: IPlayer) { } } + // Create popup + const popupId = "purchase-sleeve-augs-popup"; // General info about buying Augmentations const info = createElement("p", { @@ -58,8 +55,10 @@ export function createSleevePurchaseAugsPopup(sleeve: Sleeve, p: IPlayer) { ].join(" "), }); - const popupId = "purchase-sleeve-augs-popup"; - const popupElems: HTMLElement[] = [info]; + // Close popup + const closeBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); + + const popupElems: HTMLElement[] = [closeBtn, info]; for (const aug of availableAugs) { const div = createElement("div", { diff --git a/src/PersonObjects/Sleeve/SleeveUI.ts b/src/PersonObjects/Sleeve/SleeveUI.ts index a9a0197fd..b8ee967a0 100644 --- a/src/PersonObjects/Sleeve/SleeveUI.ts +++ b/src/PersonObjects/Sleeve/SleeveUI.ts @@ -1,6 +1,7 @@ /** * Module for handling the Sleeve UI */ +import { createSleevePurchaseAugsPopup } from "./SleeveAugmentationsUI"; import { Sleeve } from "./Sleeve"; import { SleeveTaskType } from "./SleeveTaskTypesEnum"; import { SleeveFaq } from "./data/SleeveFaq"; @@ -277,7 +278,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems { display: "block", innerText: "Purchase Augmentations", clickListener: () => { - + createSleevePurchaseAugsPopup(sleeve, playerRef!); } }); elems.statsPanel.appendChild(elems.stats); diff --git a/src/data/codingcontracttypes.ts b/src/data/codingcontracttypes.ts index 3e13799db..f687d688a 100644 --- a/src/data/codingcontracttypes.ts +++ b/src/data/codingcontracttypes.ts @@ -898,7 +898,8 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ const sanitizedPlayerAns: string = removeBracketsFromArrayString(ans); const sanitizedPlayerAnsArr: string[] = sanitizedPlayerAns.split(","); for (let i = 0; i < sanitizedPlayerAnsArr.length; ++i) { - sanitizedPlayerAnsArr[i] = removeQuotesFromString(sanitizedPlayerAnsArr[i]); + sanitizedPlayerAnsArr[i] = removeQuotesFromString(sanitizedPlayerAnsArr[i]) + .replace(/\s/g, "");; } if (num == null || num.length === 0) { diff --git a/src/ui/displayCharacterInfo.ts b/src/ui/displayCharacterInfo.ts index 4328329c0..0eb464032 100644 --- a/src/ui/displayCharacterInfo.ts +++ b/src/ui/displayCharacterInfo.ts @@ -55,7 +55,7 @@ export function displayCharacterInfo(elem: HTMLElement, p: IPlayer) { if (src.bladeburner) { parts.push(`Bladeburner: ${numeralWrapper.formatMoney(src.bladeburner)}`) }; if (src.codingcontract) { parts.push(`Coding Contracts: ${numeralWrapper.formatMoney(src.codingcontract)}`) }; if (src.work) { parts.push(`Company Work: ${numeralWrapper.formatMoney(src.work)}`) }; - if (src.corporation) { parts.push(`Corporation: ${numeralWrapper.formatMoney(src.corporation)}}`) }; + if (src.corporation) { parts.push(`Corporation: ${numeralWrapper.formatMoney(src.corporation)}`) }; if (src.crime) { parts.push(`Crimes: ${numeralWrapper.formatMoney(src.crime)}`) }; if (src.gang) { parts.push(`Gang: ${numeralWrapper.formatMoney(src.gang)}`) }; if (src.hacking) { parts.push(`Hacking: ${numeralWrapper.formatMoney(src.hacking)}`) }; diff --git a/src/utils/helpers/is2DArray.ts b/src/utils/helpers/is2DArray.ts new file mode 100644 index 000000000..f8763921b --- /dev/null +++ b/src/utils/helpers/is2DArray.ts @@ -0,0 +1,8 @@ +// Checks whether an array is a 2D array. +// For this, a 2D array is an array which contains only other arrays. +// If one element in the array is a number or string, it is NOT a 2D array +export function is2DArray(arr: any[]): boolean { + if (arr.constructor !== Array) { return false; } + + return arr.every((e) => { return e.constructor === Array; }); +} diff --git a/utils/README.md b/utils/README.md new file mode 100644 index 000000000..7a8bd8365 --- /dev/null +++ b/utils/README.md @@ -0,0 +1,4 @@ +This directory contains anything that does not represent an actual component of +the game. Instead, it contains utility classes, functions, etc. + +The `/helper` directory contains helper functions.