Added hackAnalyze() functions. Fixed bug with gymWorkout() and Millenium Fitness Gym. Updated documentation for new functions

This commit is contained in:
danielyxie 2019-01-03 00:39:32 -08:00
parent 56a727ae48
commit ee831a87f8
14 changed files with 1126 additions and 775 deletions

@ -139,3 +139,7 @@
.cmpy-mgmt-advertising-info { .cmpy-mgmt-advertising-info {
font-size: $defaultFontSize * 0.75; font-size: $defaultFontSize * 0.75;
} }
#corporation-research-popup-box-content {
overflow-x: visible !important;
}

@ -22,7 +22,6 @@
.Treant > .researched { .Treant > .researched {
background-color: #666; background-color: #666;
pointer-events: none;
font-size: 16px; font-size: 16px;
} }

1582
dist/engine.bundle.js vendored

File diff suppressed because it is too large Load Diff

4
dist/engine.css vendored

@ -2019,6 +2019,9 @@ button {
.cmpy-mgmt-advertising-info { .cmpy-mgmt-advertising-info {
font-size: 12px; } font-size: 12px; }
#corporation-research-popup-box-content {
overflow-x: visible !important; }
/* COLORS */ /* COLORS */
/* Attributes */ /* Attributes */
#bladeburner-container a, #bladeburner-container a,
@ -2185,7 +2188,6 @@ button {
.Treant > .researched { .Treant > .researched {
background-color: #666; background-color: #666;
pointer-events: none;
font-size: 16px; } font-size: 16px; }
.Treant > .locked > div { .Treant > .locked > div {

@ -151,6 +151,22 @@ Terminal commands::
$ download *.script $ download *.script
$ download *.txt $ download *.txt
expr
^^^^
$ expr [math expression]
Evaluate a mathematical expression. The expression is evaluated in JavaScript,
and therefore all JavaScript operators should be supported.
Examples::
$ expr 5.6 * 10 - 123
$ expr 3 ** 3
Evalutes a
free free
^^^^ ^^^^

@ -74,6 +74,64 @@ weaken
weaken("foodnstuff"); weaken("foodnstuff");
hackAnalyzeThreads
^^^^^^^^^^^^^^^^
.. js:function:: hackAnalyzeThreads(hostname/ip, hackAmount)
:param string hostname/ip: IP or hostname of server to analyze
:param number hackAmount: Amount of money you want to hack from the server
:returns: The number of threads needed to hack() the server for *hackAmount* money
:RAM cost: 1 GB
This function returns the number of script threads you need when running
the `hack()` command to steal the specified amount of money from the target server.
If `hackAmount` is less than zero or greater than the amount of money available
on the server, then this function returns -1.
For example, let's say the `foodnstuff` server has $10m and you run::
hackAnalyzeThreads("foodnstuff", 1e6);
If this function returns 50, this means that if your next `hack()` call
is run on a script with 50 threads, it will steal $1m from the `foodnstuff` server.
**Warning**: The value returned by this function isn't necessarily a whole number.
hackAnalyzePercent
^^^^^^^^^^^^^^^^^^
.. js:function:: hackAnalyzePercent(hostname/ip)
:param string hostname/ip: IP or hostname of target server
:returns: The percentage of money you will steal from the target server with a single hack
:RAM cost: 1 GB
Returns the percentage of the specified server's money you will steal with a
single hack. This value is returned in **percentage form, not decimal (Netscript
functions typically return in decimal form, but not this one).**
For example, assume the following returns 1::
hackAnalyzePercent("foodnstuff");
This means that if hack the `foodnstuff` server, then you will steal 1% of its
total money. If you `hack()` using N threads, then you will steal N% of its total
money.
hackChance
^^^^^^^^^^
.. js:function:: hackChance(hostname/ip)
:param string hostname/ip: IP or hostname of target server
:returns: The chance you have of successfully hacking the target server
:RAM cost: 1 GB
Returns the chance you have of successfully hacking the specified server. This
returned value is in decimal form, not percentage.
growthAnalyze growthAnalyze
^^^^^^^^^^^^^ ^^^^^^^^^^^^^

@ -31,6 +31,12 @@ purchase will have the name "hacknet-node-0" and is referenced using index 0.
The fifth Hacknet Node you purchase will have the name "hacknet-node-4" and is The fifth Hacknet Node you purchase will have the name "hacknet-node-4" and is
referenced using index 4. referenced using index 4.
RAM Cost
--------
Accessing the `hacknet` namespace incurs a one time cost of 4 GB of RAM.
In other words, using multiple Hacknet Node API functions in a script will not cost
more than 4 GB of RAM.
numNodes numNodes
-------- --------
.. js:function:: numNodes() .. js:function:: numNodes()
@ -150,7 +156,7 @@ getCoreUpgradeCost
Returns the cost of upgrading the number of cores of the specified Hacknet Node by *n*. Returns the cost of upgrading the number of cores of the specified Hacknet Node by *n*.
If an invalid value for *n* is provided, then this function returns 0. If the If an invalid value for *n* is provided, then this function returns 0. If the
specified Hacknet Node is already at the max number of cores, then Infinity is returned. specified Hacknet Node is already at the max number of cores, then Infinity is returned.
Utilities Utilities
--------- ---------

@ -15,6 +15,8 @@ getStockSymbols
.. js:function:: getStockSymbols() .. js:function:: getStockSymbols()
:RAM cost: 2 GB
Returns an array of the symbols of the tradable stocks Returns an array of the symbols of the tradable stocks
getStockPrice getStockPrice
@ -23,6 +25,7 @@ getStockPrice
.. js:function:: getStockPrice(sym) .. js:function:: getStockPrice(sym)
:param string sym: Stock symbol :param string sym: Stock symbol
:RAM cost: 2 GB
Returns the price of a stock, given its symbol (NOT the company name). The symbol is a sequence Returns the price of a stock, given its symbol (NOT the company name). The symbol is a sequence
of two to four capital letters. of two to four capital letters.
@ -37,6 +40,7 @@ getStockPosition
.. js:function:: getStockPosition(sym) .. js:function:: getStockPosition(sym)
:param string sym: Stock symbol :param string sym: Stock symbol
:RAM cost: 2 GB
Returns an array of four elements that represents the player's position in a stock. Returns an array of four elements that represents the player's position in a stock.
@ -65,6 +69,7 @@ buyStock
:param string sym: Symbol of stock to purchase :param string sym: Symbol of stock to purchase
:param number shares: Number of shares to purchased. Must be positive. Will be rounded to nearest integer :param number shares: Number of shares to purchased. Must be positive. Will be rounded to nearest integer
:RAM cost: 2.5 GB
Attempts to purchase shares of a stock using a `Market Order <http://bitburner.wikia.com/wiki/Stock_Market#Order_Types>`_. Attempts to purchase shares of a stock using a `Market Order <http://bitburner.wikia.com/wiki/Stock_Market#Order_Types>`_.
@ -81,6 +86,7 @@ sellStock
:param string sym: Symbol of stock to sell :param string sym: Symbol of stock to sell
:param number shares: Number of shares to sell. Must be positive. Will be rounded to nearest integer :param number shares: Number of shares to sell. Must be positive. Will be rounded to nearest integer
:RAM cost: 2.5 GB
Attempts to sell shares of a stock using a `Market Order <http://bitburner.wikia.com/wiki/Stock_Market#Order_Types>`_. Attempts to sell shares of a stock using a `Market Order <http://bitburner.wikia.com/wiki/Stock_Market#Order_Types>`_.
@ -101,6 +107,7 @@ shortStock
:param string sym: Symbol of stock to short :param string sym: Symbol of stock to short
:param number shares: Number of shares to short. Must be positive. Will be rounded to nearest integer :param number shares: Number of shares to short. Must be positive. Will be rounded to nearest integer
:RAM cost: 2.5 GB
Attempts to purchase a `short <http://bitburner.wikia.com/wiki/Stock_Market#Positions:_Long_vs_Short>`_ position of a stock Attempts to purchase a `short <http://bitburner.wikia.com/wiki/Stock_Market#Positions:_Long_vs_Short>`_ position of a stock
using a `Market Order <http://bitburner.wikia.com/wiki/Stock_Market#Order_Types>`_. using a `Market Order <http://bitburner.wikia.com/wiki/Stock_Market#Order_Types>`_.
@ -119,6 +126,7 @@ sellShort
:param string sym: Symbol of stock to sell :param string sym: Symbol of stock to sell
:param number shares: Number of shares to sell. Must be positive. Will be rounded to nearest integer :param number shares: Number of shares to sell. Must be positive. Will be rounded to nearest integer
:RAM cost: 2.5 GB
Attempts to sell a `short <http://bitburner.wikia.com/wiki/Stock_Market#Positions:_Long_vs_Short>`_ position of a stock Attempts to sell a `short <http://bitburner.wikia.com/wiki/Stock_Market#Positions:_Long_vs_Short>`_ position of a stock
using a `Market Order <http://bitburner.wikia.com/wiki/Stock_Market#Order_Types>`_. using a `Market Order <http://bitburner.wikia.com/wiki/Stock_Market#Order_Types>`_.
@ -149,6 +157,7 @@ placeOrder
:param string pos: :param string pos:
Specifies whether the order is a "Long" or "Short" position. The Values "L" or "S" can also be used. This is Specifies whether the order is a "Long" or "Short" position. The Values "L" or "S" can also be used. This is
NOT case-sensitive. NOT case-sensitive.
:RAM cost: 2.5 GB
Places an order on the stock market. This function only works for `Limit and Stop Orders <http://bitburner.wikia.com/wiki/Stock_Market#Order_Types>`_. Places an order on the stock market. This function only works for `Limit and Stop Orders <http://bitburner.wikia.com/wiki/Stock_Market#Order_Types>`_.
@ -175,17 +184,88 @@ cancelOrder
:param string pos: :param string pos:
Specifies whether the order is a "Long" or "Short" position. The Values "L" or "S" can also be used. This is Specifies whether the order is a "Long" or "Short" position. The Values "L" or "S" can also be used. This is
NOT case-sensitive. NOT case-sensitive.
:RAM cost: 2.5 GB
Cancels an oustanding Limit or Stop order on the stock market. Cancels an oustanding Limit or Stop order on the stock market.
The ability to use limit and stop orders is **not** immediately available to the player and must be unlocked later on in the game. The ability to use limit and stop orders is **not** immediately available to the player and must be unlocked later on in the game.
getOrders
---------
.. js:function:: getOrders()
:RAM cost: 2.5 GB
Returns your order book for the stock market. This is an object containing information
for all the Limit and Stop Orders you have in the stock market.
The object has the following structure::
{
StockSymbol1: [ // Array of orders for this stock
{
shares: Order quantity
price: Order price
type: Order type
position: Either "L" or "S" for Long or Short position
},
{
...
},
...
],
StockSymbol2: [ // Array of orders for this stock
...
],
...
}
The "Order type" property can have one of the following four values:
* "Limit Buy Order"
* "Limit Sell Order"
* "Stop Buy Order"
* "Stop Sell Order"
**Note that the order book will only contain information for stocks that you actually
have orders in**. For example, if you do not have orders in Nova Medical (NVMD), then the returned
object will not have a "NVMD" property.
Example::
{
ECP: [
{
shares: 5,
price: 100,000
type: "Stop Buy Order",
position: "S",
},
{
shares: 25,
price: 125,000
type: "Limit Sell Order",
position: "L",
},
],
SYSC: [
{
shares: 100,
price: 10,000
type: "Limit Buy Order",
position: "L",
},
],
}
getStockVolatility getStockVolatility
------------------ ------------------
.. js:function:: getStockVolatility(sym) .. js:function:: getStockVolatility(sym)
:param string sym: Symbol of stock :param string sym: Symbol of stock
:RAM cost: 2.5 GB
Returns the volatility of the specified stock. Returns the volatility of the specified stock.
@ -203,6 +283,7 @@ getStockForecast
.. js:function:: getStockForecast(sym) .. js:function:: getStockForecast(sym)
:param string sym: Symbol of stock :param string sym: Symbol of stock
:RAM cost: 2.5 GB
Returns the probability that the specified stock's price will increase Returns the probability that the specified stock's price will increase
(as opposed to decrease) during the next tick. (as opposed to decrease) during the next tick.
@ -220,6 +301,8 @@ purchase4SMarketData
.. js:function:: purchase4SMarketData() .. js:function:: purchase4SMarketData()
:RAM cost: 2.5 GB
Purchase 4S Market Data Access. Purchase 4S Market Data Access.
Returns true if you successfully purchased it or if you already have access. Returns true if you successfully purchased it or if you already have access.
@ -230,6 +313,8 @@ purchase4SMarketDataTixApi
.. js:function:: purchase4SMarketDataTixApi() .. js:function:: purchase4SMarketDataTixApi()
:RAM cost: 2.5 GB
Purchase 4S Market Data TIX API Access. Purchase 4S Market Data TIX API Access.
Returns true if you successfully purchased it or if you already have access. Returns true if you successfully purchased it or if you already have access.

@ -59,7 +59,8 @@ var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules;
var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*"; var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*";
let NetscriptFunctions = let NetscriptFunctions =
"hack|sleep|grow|weaken|growthAnalyze|print|tprint|scan|nuke|brutessh|" + "hack|hackAnalyzeThreads|hackAnalyzePercent|hackChance|" +
"sleep|grow|weaken|growthAnalyze|print|tprint|scan|nuke|brutessh|" +
"ftpcrack|" + "ftpcrack|" +
"clearLog|disableLog|enableLog|isLogEnabled|getScriptLogs|" + "clearLog|disableLog|enableLog|isLogEnabled|getScriptLogs|" +
"relaysmtp|httpworm|sqlinject|run|exec|spawn|kill|killall|exit|" + "relaysmtp|httpworm|sqlinject|run|exec|spawn|kill|killall|exit|" +

@ -1,6 +1,5 @@
import { BitNodeMultipliers } from "./BitNodeMultipliers"; import { BitNodeMultipliers } from "./BitNodeMultipliers";
import { CONSTANTS } from "./Constants"; import { CONSTANTS } from "./Constants";
import { Engine } from "./engine";
import { Factions, import { Factions,
factionExists } from "./Faction/Factions"; factionExists } from "./Faction/Factions";
import { hasBladeburnerSF } from "./NetscriptFunctions"; import { hasBladeburnerSF } from "./NetscriptFunctions";
@ -18,6 +17,7 @@ import { dialogBoxCreate } from "../utils/DialogBox";
import { createAccordionElement } from "../utils/uiHelpers/createAccordionElement"; import { createAccordionElement } from "../utils/uiHelpers/createAccordionElement";
import { Reviver, Generic_toJSON, import { Reviver, Generic_toJSON,
Generic_fromJSON } from "../utils/JSONReviver"; Generic_fromJSON } from "../utils/JSONReviver";
import { formatNumber } from "../utils/StringHelperFunctions";
import { clearObject } from "../utils/helpers/clearObject"; import { clearObject } from "../utils/helpers/clearObject";
import { createElement } from "../utils/uiHelpers/createElement"; import { createElement } from "../utils/uiHelpers/createElement";
import { isString } from "../utils/helpers/isString"; import { isString } from "../utils/helpers/isString";
@ -2475,9 +2475,9 @@ function giveAllAugmentations() {
Player.reapplyAllAugmentations(); Player.reapplyAllAugmentations();
} }
function displayAugmentationsContent() { function displayAugmentationsContent(contentEl) {
removeChildrenFromElement(Engine.Display.augmentationsContent); removeChildrenFromElement(contentEl);
Engine.Display.augmentationsContent.appendChild(createElement("h1", { contentEl.appendChild(createElement("h1", {
innerText:"Purchased Augmentations", innerText:"Purchased Augmentations",
})); }));
@ -2487,7 +2487,7 @@ function displayAugmentationsContent() {
bladeburnerText = "Bladeburner Progress\n\n"; bladeburnerText = "Bladeburner Progress\n\n";
} }
Engine.Display.augmentationsContent.appendChild(createElement("pre", { contentEl.appendChild(createElement("pre", {
width:"70%", whiteSpace:"pre-wrap", display:"block", width:"70%", whiteSpace:"pre-wrap", display:"block",
innerText:"Below is a list of all Augmentations you have purchased but not yet installed. Click the button below to install them.\n" + innerText:"Below is a list of all Augmentations you have purchased but not yet installed. Click the button below to install them.\n" +
"WARNING: Installing your Augmentations resets most of your progress, including:\n\n" + "WARNING: Installing your Augmentations resets most of your progress, including:\n\n" +
@ -2505,7 +2505,7 @@ function displayAugmentationsContent() {
})); }));
//Install Augmentations button //Install Augmentations button
Engine.Display.augmentationsContent.appendChild(createElement("a", { contentEl.appendChild(createElement("a", {
class:"a-link-button", innerText:"Install Augmentations", class:"a-link-button", innerText:"Install Augmentations",
tooltip:"'I never asked for this'", tooltip:"'I never asked for this'",
clickListener:()=>{ clickListener:()=>{
@ -2515,7 +2515,7 @@ function displayAugmentationsContent() {
})); }));
//Backup button //Backup button
Engine.Display.augmentationsContent.appendChild(createElement("a", { contentEl.appendChild(createElement("a", {
class:"a-link-button flashing-button", innerText:"Backup Save (Export)", class:"a-link-button flashing-button", innerText:"Backup Save (Export)",
tooltip:"It's always a good idea to backup/export your save!", tooltip:"It's always a good idea to backup/export your save!",
clickListener:()=>{ clickListener:()=>{
@ -2539,13 +2539,13 @@ function displayAugmentationsContent() {
var accordion = createAccordionElement({hdrText:displayName, panelText:aug.info}); var accordion = createAccordionElement({hdrText:displayName, panelText:aug.info});
queuedAugmentationsList.appendChild(accordion[0]); queuedAugmentationsList.appendChild(accordion[0]);
} }
Engine.Display.augmentationsContent.appendChild(queuedAugmentationsList); contentEl.appendChild(queuedAugmentationsList);
//Installed augmentations list //Installed augmentations list
Engine.Display.augmentationsContent.appendChild(createElement("h1", { contentEl.appendChild(createElement("h1", {
innerText:"Installed Augmentations", marginTop:"8px", innerText:"Installed Augmentations", marginTop:"8px",
})); }));
Engine.Display.augmentationsContent.appendChild(createElement("p", { contentEl.appendChild(createElement("p", {
width:"70%", whiteSpace:"pre-wrap", width:"70%", whiteSpace:"pre-wrap",
innerText:"List of all Augmentations (including Source Files) that have been " + innerText:"List of all Augmentations (including Source Files) that have been " +
"installed. You have gained the effects of these Augmentations." "installed. You have gained the effects of these Augmentations."
@ -2554,7 +2554,7 @@ function displayAugmentationsContent() {
var augmentationsList = createElement("ul", {class:"augmentations-list"}); var augmentationsList = createElement("ul", {class:"augmentations-list"});
//Expand/Collapse All buttons //Expand/Collapse All buttons
Engine.Display.augmentationsContent.appendChild(createElement("a", { contentEl.appendChild(createElement("a", {
class:"a-link-button", fontSize:"14px", innerText:"Expand All", display:"inline-block", class:"a-link-button", fontSize:"14px", innerText:"Expand All", display:"inline-block",
clickListener:()=>{ clickListener:()=>{
var allHeaders = augmentationsList.getElementsByClassName("accordion-header"); var allHeaders = augmentationsList.getElementsByClassName("accordion-header");
@ -2563,7 +2563,7 @@ function displayAugmentationsContent() {
} }
} }
})); }));
Engine.Display.augmentationsContent.appendChild(createElement("a", { contentEl.appendChild(createElement("a", {
class:"a-link-button", fontSize:"14px", innerText:"Collapse All", display:"inline-block", class:"a-link-button", fontSize:"14px", innerText:"Collapse All", display:"inline-block",
clickListener:()=>{ clickListener:()=>{
var allHeaders = augmentationsList.getElementsByClassName("accordion-header"); var allHeaders = augmentationsList.getElementsByClassName("accordion-header");
@ -2595,7 +2595,7 @@ function displayAugmentationsContent() {
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.Alphabetically; Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.Alphabetically;
} }
}); });
Engine.Display.augmentationsContent.appendChild(sortInOrderButton); contentEl.appendChild(sortInOrderButton);
const sortByAcquirementTimeButton = createElement("a", { const sortByAcquirementTimeButton = createElement("a", {
class:"a-link-button", fontSize:"14px", innerText:"Sort by Acquirement Time", class:"a-link-button", fontSize:"14px", innerText:"Sort by Acquirement Time",
@ -2608,15 +2608,47 @@ function displayAugmentationsContent() {
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.AcquirementTime; Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.AcquirementTime;
} }
}); });
Engine.Display.augmentationsContent.appendChild(sortByAcquirementTimeButton); contentEl.appendChild(sortByAcquirementTimeButton);
//Source Files - Temporary...Will probably put in a separate pane Later
if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) { if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) {
sortInOrderButton.click(); sortInOrderButton.click();
} else { } else {
sortByAcquirementTimeButton.click(); sortByAcquirementTimeButton.click();
} }
Engine.Display.augmentationsContent.appendChild(augmentationsList); contentEl.appendChild(augmentationsList);
// Display multiplier information at the bottom
contentEl.appendChild(createElement("p", {
display: "block",
innerHTML:
`<br><br><strong><u>Total Multipliers:</u></strong><br>` +
'Hacking Chance multiplier: ' + formatNumber(Player.hacking_chance_mult * 100, 2) + '%<br>' +
'Hacking Speed multiplier: ' + formatNumber(Player.hacking_speed_mult * 100, 2) + '%<br>' +
'Hacking Money multiplier: ' + formatNumber(Player.hacking_money_mult * 100, 2) + '%<br>' +
'Hacking Growth multiplier: ' + formatNumber(Player.hacking_grow_mult * 100, 2) + '%<br><br>' +
'Hacking Level multiplier: ' + formatNumber(Player.hacking_mult * 100, 2) + '%<br>' +
'Hacking Experience multiplier: ' + formatNumber(Player.hacking_exp_mult * 100, 2) + '%<br><br>' +
'Strength Level multiplier: ' + formatNumber(Player.strength_mult * 100, 2) + '%<br>' +
'Strength Experience multiplier: ' + formatNumber(Player.strength_exp_mult * 100, 2) + '%<br><br>' +
'Defense Level multiplier: ' + formatNumber(Player.defense_mult * 100, 2) + '%<br>' +
'Defense Experience multiplier: ' + formatNumber(Player.defense_exp_mult * 100, 2) + '%<br><br>' +
'Dexterity Level multiplier: ' + formatNumber(Player.dexterity_mult * 100, 2) + '%<br>' +
'Dexterity Experience multiplier: ' + formatNumber(Player.dexterity_exp_mult * 100, 2) + '%<br><br>' +
'Agility Level multiplier: ' + formatNumber(Player.agility_mult * 100, 2) + '%<br>' +
'Agility Experience multiplier: ' + formatNumber(Player.agility_exp_mult * 100, 2) + '%<br><br>' +
'Charisma Level multiplier: ' + formatNumber(Player.charisma_mult * 100, 2) + '%<br>' +
'Charisma Experience multiplier: ' + formatNumber(Player.charisma_exp_mult * 100, 2) + '%<br><br>' +
'Hacknet Node production multiplier: ' + formatNumber(Player.hacknet_node_money_mult * 100, 2) + '%<br>' +
'Hacknet Node purchase cost multiplier: ' + formatNumber(Player.hacknet_node_purchase_cost_mult * 100, 2) + '%<br>' +
'Hacknet Node RAM upgrade cost multiplier: ' + formatNumber(Player.hacknet_node_ram_cost_mult * 100, 2) + '%<br>' +
'Hacknet Node Core purchase cost multiplier: ' + formatNumber(Player.hacknet_node_core_cost_mult * 100, 2) + '%<br>' +
'Hacknet Node level upgrade cost multiplier: ' + formatNumber(Player.hacknet_node_level_cost_mult * 100, 2) + '%<br><br>' +
'Company reputation gain multiplier: ' + formatNumber(Player.company_rep_mult * 100, 2) + '%<br>' +
'Faction reputation gain multiplier: ' + formatNumber(Player.faction_rep_mult * 100, 2) + '%<br>' +
'Salary multiplier: ' + formatNumber(Player.work_money_mult * 100, 2) + '%<br>' +
'Crime success multiplier: ' + formatNumber(Player.crime_success_mult * 100, 2) + '%<br>' +
'Crime money multiplier: ' + formatNumber(Player.crime_money_mult * 100, 2) + '%<br><br><br>',
}))
} }
//Creates the accordion elements to display Augmentations //Creates the accordion elements to display Augmentations

@ -55,6 +55,7 @@ export let CONSTANTS: IMap<any> = {
ScriptForRamCost: 0, ScriptForRamCost: 0,
ScriptIfRamCost: 0, ScriptIfRamCost: 0,
ScriptHackRamCost: 0.1, ScriptHackRamCost: 0.1,
ScriptHackAnalyzeRamCost: 1,
ScriptGrowRamCost: 0.15, ScriptGrowRamCost: 0.15,
ScriptGrowthAnalyzeRamCost: 1, ScriptGrowthAnalyzeRamCost: 1,
ScriptWeakenRamCost: 0.15, ScriptWeakenRamCost: 0.15,
@ -520,11 +521,16 @@ export let CONSTANTS: IMap<any> = {
* Added getOrders() Netscript function to the TIX API * Added getOrders() Netscript function to the TIX API
* Added getAugmentationPrereq() Singularity function (by havocmayhem) * Added getAugmentationPrereq() Singularity function (by havocmayhem)
* Added hackAnalyzePercent() and hackAnalyzeThreads() Netscript functions
* Stock Market, Travel, and Corporation main menu links are now properly styled * Stock Market, Travel, and Corporation main menu links are now properly styled
* Many pop-up/dialog boxes now support the 'Enter' and 'Esc' hotkeys. If you find a pop-up/dialog box that doesnt support this, let me know specifically which one ('Enter' for the default option, 'Esc' for cancelling and closing the pop-up box) * Many pop-up/dialog boxes now support the 'Enter' and 'Esc' hotkeys. If you find a pop-up/dialog box that doesnt support this, let me know specifically which one ('Enter' for the default option, 'Esc' for cancelling and closing the pop-up box)
* Added "brace_style = preserve_inline" configuration to Script Editor Beautifier * Added "brace_style = preserve_inline" configuration to Script Editor Beautifier
* ServerProfiler.exe can now be purchased from the Dark Web * ServerProfiler.exe can now be purchased from the Dark Web
* Added an option to copy save data to clipboard * Added an option to copy save data to clipboard
* Added total multiplier information on the "Augmentations" page
* Bug Fix: gymWorkout() Singularity function should now work properly with Millenium Fitness Gym
* Began migrating gameplay information to the ReadTheDocs documentation
*
` `
} }

@ -1265,6 +1265,11 @@ Industry.prototype.createResearchBox = function() {
// Add Event Listeners for all Nodes // Add Event Listeners for all Nodes
const allResearch = researchTree.getAllNodes(); const allResearch = researchTree.getAllNodes();
for (let i = 0; i < allResearch.length; ++i) { for (let i = 0; i < allResearch.length; ++i) {
// If this is already Researched, skip it
if (this.researched[allResearch[i]] === true) {
continue;
}
// Get the Research object // Get the Research object
const research = ResearchMap[allResearch[i]]; const research = ResearchMap[allResearch[i]];
@ -3842,11 +3847,12 @@ Corporation.prototype.updateCorporationOverviewContent = function() {
const dividendsPerShare = totalDividends / TOTALSHARES; const dividendsPerShare = totalDividends / TOTALSHARES;
const playerEarnings = this.numShares * dividendsPerShare; const playerEarnings = this.numShares * dividendsPerShare;
dividendStr = `Retained Profits (after dividends): ${numeralWrapper.format(retainedEarnings, "$0.000a")} / s<br>` + dividendStr = `Dividend Percentage: ${numeralWrapper.format(this.dividendPercentage / 100, "0%")}<br>` +
`Retained Profits (after dividends): ${numeralWrapper.format(retainedEarnings, "$0.000a")} / s<br>` +
`Dividends per share: ${numeralWrapper.format(dividendsPerShare, "$0.000a")} / s<br>` + `Dividends per share: ${numeralWrapper.format(dividendsPerShare, "$0.000a")} / s<br>` +
`Your earnings (Pre-Tax): ${numeralWrapper.format(playerEarnings, "$0.000a")} / s<br>` + `Your earnings as a shareholder (Pre-Tax): ${numeralWrapper.format(playerEarnings, "$0.000a")} / s<br>` +
`Dividend Tax Rate: ${this.dividendTaxPercentage}%<br>` + `Dividend Tax Rate: ${this.dividendTaxPercentage}%<br>` +
`Your earnings (Post-Tax): ${numeralWrapper.format(playerEarnings * (this.dividendTaxPercentage / 100), "$0.000a")} / s<br>`; `Your earnings as a shareholder (Post-Tax): ${numeralWrapper.format(playerEarnings * (this.dividendTaxPercentage / 100), "$0.000a")} / s<br>`;
} }
var txt = "Total Funds: " + numeralWrapper.format(this.funds.toNumber(), '$0.000a') + "<br>" + var txt = "Total Funds: " + numeralWrapper.format(this.funds.toNumber(), '$0.000a') + "<br>" +
@ -4186,9 +4192,6 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
id: "cmpy-mgmt-employee-p", id: "cmpy-mgmt-employee-p",
display:"block", display:"block",
innerHTML: "<h1>Office Space</h1><br>" + innerHTML: "<h1>Office Space</h1><br>" +
"Type: " + office.tier + "<br>" +
"Comfort: " + office.comf + "<br>" +
"Beauty: " + office.beau + "<br>" +
"Size: " + office.employees.length + " / " + office.size + " employees", "Size: " + office.employees.length + " / " + office.size + " employees",
}); });
industryEmployeePanel.appendChild(industryEmployeeText); industryEmployeePanel.appendChild(industryEmployeeText);
@ -4640,9 +4643,6 @@ Corporation.prototype.updateDivisionContent = function(division) {
var office = division.offices[currentCityUi]; var office = division.offices[currentCityUi];
industryEmployeeText.innerHTML = industryEmployeeText.innerHTML =
"<h1>Office Space</h1><br>" + "<h1>Office Space</h1><br>" +
"Type: " + office.tier + "<br>" +
"Comfort: " + office.comf + "<br>" +
"Beauty: " + office.beau + "<br>" +
"Size: " + office.employees.length + " / " + office.size + " employees"; "Size: " + office.employees.length + " / " + office.size + " employees";
if (office.employees.length >= office.size) { if (office.employees.length >= office.size) {
industryEmployeeHireButton.className = "a-link-button-inactive"; industryEmployeeHireButton.className = "a-link-button-inactive";
@ -4657,12 +4657,13 @@ Corporation.prototype.updateDivisionContent = function(division) {
//Employee Overview stats //Employee Overview stats
//Calculate average morale, happiness, and energy //Calculate average morale, happiness, and energy
var totalMorale = 0, totalHappiness = 0, totalEnergy = 0, var totalMorale = 0, totalHappiness = 0, totalEnergy = 0, totalSalary = 0,
avgMorale = 0, avgHappiness = 0, avgEnergy = 0; avgMorale = 0, avgHappiness = 0, avgEnergy = 0;
for (var i = 0; i < office.employees.length; ++i) { for (let i = 0; i < office.employees.length; ++i) {
totalMorale += office.employees[i].mor; totalMorale += office.employees[i].mor;
totalHappiness += office.employees[i].hap; totalHappiness += office.employees[i].hap;
totalEnergy += office.employees[i].ene; totalEnergy += office.employees[i].ene;
totalSalary += office.employees[i].sal;
} }
if (office.employees.length > 0) { if (office.employees.length > 0) {
avgMorale = totalMorale / office.employees.length; avgMorale = totalMorale / office.employees.length;
@ -4672,7 +4673,8 @@ Corporation.prototype.updateDivisionContent = function(division) {
industryEmployeeInfo.innerHTML = industryEmployeeInfo.innerHTML =
"Avg Employee Morale: " + formatNumber(avgMorale, 3) + "<br>" + "Avg Employee Morale: " + formatNumber(avgMorale, 3) + "<br>" +
"Avg Employee Happiness: " + formatNumber(avgHappiness, 3) + "<br>" + "Avg Employee Happiness: " + formatNumber(avgHappiness, 3) + "<br>" +
"Avg Employee Energy: " + formatNumber(avgEnergy, 3); "Avg Employee Energy: " + formatNumber(avgEnergy, 3) + "<br>" +
"Total Employee Salary: " + numeralWrapper.format(totalSalary, "$0.000a");
if (vechain) { //VeChain - Statistics if (vechain) { //VeChain - Statistics
industryEmployeeInfo.appendChild(createElement("br", {})); industryEmployeeInfo.appendChild(createElement("br", {}));
industryEmployeeInfo.appendChild(createElement("p", { industryEmployeeInfo.appendChild(createElement("p", {

@ -408,6 +408,46 @@ function NetscriptFunctions(workerScript) {
} }
}); });
}, },
hackAnalyzeThreads : function(ip, hackAmount) {
if (workerScript.checkingRam) {
return updateStaticRam("hackAnalyzeThreads", CONSTANTS.ScriptHackAnalyzeRamCost);
}
updateDynamicRam("hackAnalyzeThreads", CONSTANTS.ScriptHackAnalyzeRamCost);
// Check argument validity
const server = safeGetServer(ip, 'hackAnalyzeThreads');
if (isNaN(hackAmount)) {
throw makeRuntimeRejectMsg(workerScript, `Invalid growth argument passed into growthAnalyze: ${hackAmount}. Must be numeric`);
}
if (hackAmount < 0 || hackAmount > server.moneyAvailable) {
return -1;
}
const percentHacked = calculatePercentMoneyHacked(server);
return hackAmount / Math.floor(server.moneyAvailable * percentHacked);
},
hackAnalyzePercent : function(ip) {
if (workerScript.checkingRam) {
return updateStaticRam("hackAnalyzePercent", CONSTANTS.ScriptHackAnalyzeRamCost);
}
updateDynamicRam("hackAnalyzePercent", CONSTANTS.ScriptHackAnalyzeRamCost);
const server = safeGetServer(ip, 'hackAnalyzePercent');
return calculatePercentMoneyHacked(server) * 100;
},
hackChance : function(ip) {
if (workerScript.checkingRam) {
return updateStaticRam("hackChance", CONSTANTS.ScriptHackAnalyzeRamCost);
}
updateDynamicRam("hackChance", CONSTANTS.ScriptHackAnalyzeRamCost);
const server = safeGetServer(ip, 'hackChance');
return calculateHackingChance(server);
},
sleep : function(time){ sleep : function(time){
if (workerScript.checkingRam) {return 0;} if (workerScript.checkingRam) {return 0;}
if (time === undefined) { if (time === undefined) {
@ -2626,7 +2666,7 @@ function NetscriptFunctions(workerScript) {
costMult = 20; costMult = 20;
expMult = 10; expMult = 10;
break; break;
case Locations.VolhavenMilleniumFitnessGym: case Locations.VolhavenMilleniumFitnessGym.toLowerCase():
if (Player.city != Locations.Volhaven) { if (Player.city != Locations.Volhaven) {
workerScript.scriptRef.log("ERROR: You cannot workout at Millenium Fitness Gym because you are not in Volhaven. gymWorkout() failed"); workerScript.scriptRef.log("ERROR: You cannot workout at Millenium Fitness Gym because you are not in Volhaven. gymWorkout() failed");
return false; return false;

@ -325,7 +325,7 @@ const Engine = {
loadAugmentationsContent: function() { loadAugmentationsContent: function() {
Engine.hideAllContent(); Engine.hideAllContent();
Engine.Display.augmentationsContent.style.display = "block"; Engine.Display.augmentationsContent.style.display = "block";
displayAugmentationsContent(); displayAugmentationsContent(Engine.Display.augmentationsContent);
routing.navigateTo(Page.Augmentations); routing.navigateTo(Page.Augmentations);
document.getElementById("augmentations-menu-link").classList.add("active"); document.getElementById("augmentations-menu-link").classList.add("active");
}, },