Merge branch 'v0.40.3-patch-2' of https://github.com/danielyxie/bitburner into stock-market-and-bladeburner-rebalancing

This commit is contained in:
danielyxie 2018-09-05 16:38:19 -05:00
commit f0151db5d1
8 changed files with 276 additions and 245 deletions

@ -3,9 +3,10 @@ Netscript Documentation
Netscript is the programming language used in the world of Bitburner. Netscript is the programming language used in the world of Bitburner.
When you write scripts in Bitburner, they are written in the Netscript language. When you write scripts in Bitburner, they are written in the Netscript language.
Netscript is simply a tiny subset of Javascript. This means that Netscript's Netscript is simply a subset of `JavaScript <https://developer.mozilla.org/en-US/docs/Web/JavaScript>`_,.
syntax is almost idental to Javascript's, but it does not implement many of the This means that Netscript's syntax is
features that Javascript has. identical to that of JavaScript, but it does not implement some of the features
that JavaScript has.
If you have any requests or suggestions to improve the Netscript language, feel free If you have any requests or suggestions to improve the Netscript language, feel free
to reach out to the developer! to reach out to the developer!

@ -2,14 +2,18 @@
Netscript 1.0 Netscript 1.0
============= =============
Netscript 1.0 is implemented using modified version of Neil Fraser's Netscript 1.0 is implemented using a modified version of Neil Fraser's
`JS-Interpreter <https://github.com/NeilFraser/JS-Interpreter>`_. `JS-Interpreter <https://github.com/NeilFraser/JS-Interpreter>`_.
This interpreter was created for ES5, which means that the code written This is an ES5 JavaScript interpreter. This means that (almost) any JavaScript feature
for Netscript 1.0 must be compliant for that version. However, some additional that is available in ES5 is also available in Netscript 1.0. However, this also means
ES6+ features are implemented through polyfills. that the interpreter does not natively support any JavaScript features introduced in versions
ES6 or after.
Netscript 1.0 scripts end with the ".script" extension. If you are confused by the ES5/ES6/etc. terminology, consider reading this:
`WTF is ES6, ES8, ES2017, ECMAScript... <https://codeburst.io/javascript-wtf-is-es6-es8-es-2017-ecmascript-dca859e4821c>`_
Netscript 1.0 scripts end with the ".script" extension in their filenames.
Which ES6+ features are supported? Which ES6+ features are supported?
---------------------------------- ----------------------------------

@ -772,6 +772,18 @@ write
is set to "w", then the data is written in "write" mode which means that it will overwrite all existing data on the text file. If *mode* is set to is set to "w", then the data is written in "write" mode which means that it will overwrite all existing data on the text file. If *mode* is set to
any other value then the data will be written in "append" mode which means that the data will be added at the end of the text file. any other value then the data will be written in "append" mode which means that the data will be added at the end of the text file.
tryWrite
^^^^^^^^
.. js:function:: tryWrite(port, data="")
:param number port: Port to be written to
:param string data: Data to try to write
:returns: True if the data is successfully written to the port, and false otherwise
Attempts to write data to the specified Netscript Port. If the port is full, the data will
not be written. Otherwise, the data will be written normally
read read
^^^^ ^^^^
@ -813,6 +825,17 @@ clear
If the *port/fn* argument is a string, then it specifies the name of a text file (.txt) and will delete all data from that text file. If the *port/fn* argument is a string, then it specifies the name of a text file (.txt) and will delete all data from that text file.
getPortHandle
^^^^^^^^^^^^^
.. js:function:: getPortHandle(port)
:param number port: Port number
Get a handle to a Netscript Port. See more details here: :ref:`netscript_ports`
**WARNING:** Port Handles only work in :ref:`netscriptjs`. They will not work in :ref:`netscript1`.
rm rm
^^ ^^

@ -1,9 +1,13 @@
.. _netscript_misc:
Netscript Miscellaneous Netscript Miscellaneous
======================= =======================
.. _netscript_ports:
Netscript Ports Netscript Ports
--------------- ---------------
Netscript ports are endpoints that can be used to communicate between scripts. Netscript Ports are endpoints that can be used to communicate between scripts.
A port is implemented as a sort of serialized queue, where you can only write A port is implemented as a sort of serialized queue, where you can only write
and read one element at a time from the port. When you read data from a port, and read one element at a time from the port. When you read data from a port,
the element that is read is removed from the port. the element that is read is removed from the port.
@ -55,9 +59,11 @@ And the data in port 1 will look like::
**Port Handles** **Port Handles**
WARNING: Port Handles only work in :ref:`netscriptjs`. They do not work in :ref:`netscript1`
The :js:func:`getPortHandle` Netscript function can be used to get a handle to a Netscript Port. The :js:func:`getPortHandle` Netscript function can be used to get a handle to a Netscript Port.
This handle allows you to access several new port-related functions and the This handle allows you to access several new port-related functions and the
port's underlying data structure, which is just a Javascript array. The functions are: port's underlying data structure, which is just a JavaScript array. The functions are:
.. js:method:: NetscriptPort.write(data) .. js:method:: NetscriptPort.write(data)

@ -6,6 +6,9 @@ let CONSTANTS = {
//the player will have this level assuming no multipliers. Multipliers can cause skills to go above this. //the player will have this level assuming no multipliers. Multipliers can cause skills to go above this.
MaxSkillLevel: 975, MaxSkillLevel: 975,
//Milliseconds per game cycle
MilliPerCycle: 200,
//How much reputation is needed to join a megacorporation's faction //How much reputation is needed to join a megacorporation's faction
CorpFactionRepRequirement: 200e3, CorpFactionRepRequirement: 200e3,
@ -493,12 +496,13 @@ let CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.40.3<br>" + `v0.40.3<br>
"* b1t_flum3.exe program can now be created immediately at Hacking level 1 (rather than hacking level 5)<br>" + * b1t_flum3.exe program can now be created immediately at Hacking level 1 (rather than hacking level 5)
"* UI improvements for the character overview panel and the left-hand menu (by mat-jaworski)<br>" + * UI improvements for the character overview panel and the left-hand menu (by mat-jaworski)
"* Improved the introductory tutorial<br>" * Updated documentation to reflect the fact that Netscript port handles (getPortHandle()) only works in NetscriptJS (2.0), NOT Netscript 1.0
* Added tryWrite() Netscript function
* When working (for a company/faction), experience is gained immediately/continuously rather than all at once when the work is finished
* Improved the introductory tutorial`
} }
export {CONSTANTS}; export {CONSTANTS};

@ -268,7 +268,7 @@ function iTutorialEvaluateStep() {
"written in the Netscript language, a programming language created for " + "written in the Netscript language, a programming language created for " +
"this game. <strong style='background-color:#444;'>There are details about the Netscript language in the documentation, which " + "this game. <strong style='background-color:#444;'>There are details about the Netscript language in the documentation, which " +
"can be accessed in the 'Tutorial' tab on the main navigation menu. I highly suggest you check " + "can be accessed in the 'Tutorial' tab on the main navigation menu. I highly suggest you check " +
"it out after this tutorial. </strong> For now, just copy " + "it out after this tutorial.</strong> For now, just copy " +
"and paste the following code into the script editor: <br><br>" + "and paste the following code into the script editor: <br><br>" +
"while(true) { <br>" + "while(true) { <br>" +
"&nbsp;&nbsp;hack('foodnstuff'); <br>" + "&nbsp;&nbsp;hack('foodnstuff'); <br>" +

@ -1847,6 +1847,25 @@ function NetscriptFunctions(workerScript) {
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for write: " + port); throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for write: " + port);
} }
}, },
tryWrite : function(port, data="") {
if (workerScript.checkingRam) {
return updateStaticRam("tryWrite", CONSTANTS.ScriptReadWriteRamCost);
}
updateDynamicRam("tryWrite", CONSTANTS.ScriptReadWriteRamCost);
if (!isNaN(port)) {
port = Math.round(port);
if (port < 1 || port > CONSTANTS.NumNetscriptPorts) {
throw makeRuntimeRejectMsg(workerScript, "ERROR: tryWrite() called on invalid port: " + port + ". Only ports 1-" + CONSTANTS.NumNetscriptPorts + " are valid.");
}
var port = NetscriptPorts[port-1];
if (port == null || !(port instanceof NetscriptPort)) {
throw makeRuntimeRejectMsg(workerScript, "Could not find port: " + port + ". This is a bug contact the game developer");
}
return port.tryWrite(data);
} else {
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for tryWrite: " + port);
}
},
read : function(port) { read : function(port) {
if (workerScript.checkingRam) { if (workerScript.checkingRam) {
return updateStaticRam("read", CONSTANTS.ScriptReadWriteRamCost); return updateStaticRam("read", CONSTANTS.ScriptReadWriteRamCost);

@ -30,6 +30,8 @@ import numeral from "numeral/min/numeral.min";
import {formatNumber, import {formatNumber,
convertTimeMsToTimeElapsedString} from "../utils/StringHelperFunctions"; convertTimeMsToTimeElapsedString} from "../utils/StringHelperFunctions";
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
function PlayerObject() { function PlayerObject() {
//Skills and stats //Skills and stats
this.hacking_skill = 1; this.hacking_skill = 1;
@ -613,6 +615,7 @@ PlayerObject.prototype.resetWorkStatus = function() {
this.workChaExpGainRate = 0; this.workChaExpGainRate = 0;
this.workRepGainRate = 0; this.workRepGainRate = 0;
this.workMoneyGainRate = 0; this.workMoneyGainRate = 0;
this.workMoneyLossRate = 0;
this.workHackExpGained = 0; this.workHackExpGained = 0;
this.workStrExpGained = 0; this.workStrExpGained = 0;
@ -634,24 +637,109 @@ PlayerObject.prototype.resetWorkStatus = function() {
document.getElementById("work-in-progress-text").innerHTML = ""; document.getElementById("work-in-progress-text").innerHTML = "";
} }
PlayerObject.prototype.gainWorkExp = function() { PlayerObject.prototype.processWorkEarnings = function(numCycles=1) {
this.gainHackingExp(this.workHackExpGained); var hackExpGain = this.workHackExpGainRate * numCycles;
this.gainStrengthExp(this.workStrExpGained); var strExpGain = this.workStrExpGainRate * numCycles;
this.gainDefenseExp(this.workDefExpGained); var defExpGain = this.workDefExpGainRate * numCycles;
this.gainDexterityExp(this.workDexExpGained); var dexExpGain = this.workDexExpGainRate * numCycles;
this.gainAgilityExp(this.workAgiExpGained); var agiExpGain = this.workAgiExpGainRate * numCycles;
this.gainCharismaExp(this.workChaExpGained); var chaExpGain = this.workChaExpGainRate * numCycles;
this.gainHackingExp(hackExpGain);
this.gainStrengthExp(strExpGain);
this.gainDefenseExp(defExpGain);
this.gainDexterityExp(dexExpGain);
this.gainAgilityExp(agiExpGain);
this.gainCharismaExp(chaExpGain);
this.workHackExpGained += hackExpGain;
this.workStrExpGained += strExpGain;
this.workDefExpGained += defExpGain;
this.workDexExpGained += dexExpGain;
this.workAgiExpGained += agiExpGain;
this.workChaExpGained += chaExpGain;
this.workRepGained += this.workRepGainRate * numCycles;
this.workMoneyGained += this.workMoneyGainRate * numCycles;
this.workMoneyGained -= this.workMoneyLossRate * numCycles;
} }
/* Working for Company */ /* Working for Company */
PlayerObject.prototype.startWork = function() {
this.resetWorkStatus();
this.isWorking = true;
this.workType = CONSTANTS.WorkTypeCompany;
this.workHackExpGainRate = this.getWorkHackExpGain();
this.workStrExpGainRate = this.getWorkStrExpGain();
this.workDefExpGainRate = this.getWorkDefExpGain();
this.workDexExpGainRate = this.getWorkDexExpGain();
this.workAgiExpGainRate = this.getWorkAgiExpGain();
this.workChaExpGainRate = this.getWorkChaExpGain();
this.workRepGainRate = this.getWorkRepGain();
this.workMoneyGainRate = this.getWorkMoneyGain();
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
//Remove all old event listeners from Cancel button
var newCancelButton = clearEventListeners("work-in-progress-cancel-button");
newCancelButton.innerHTML = "Cancel Work";
newCancelButton.addEventListener("click", function() {
Player.finishWork(true);
return false;
});
//Display Work In Progress Screen
Engine.loadWorkInProgressContent();
}
PlayerObject.prototype.work = function(numCycles) {
//Cap the number of cycles being processed to whatever would put you at
//the work time limit (8 hours)
var overMax = false;
if (this.timeWorked + (Engine._idleSpeed * numCycles) >= CONSTANTS.MillisecondsPer8Hours) {
overMax = true;
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / Engine._idleSpeed);
}
this.timeWorked += Engine._idleSpeed * numCycles;
this.workRepGainRate = this.getWorkRepGain();
this.processWorkEarnings(numCycles);
//If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money
if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
return this.finishWork(false);
}
var comp = Companies[this.companyName], companyRep = "0";
if (comp == null || !(comp instanceof Company)) {
console.log("ERROR: Could not find Company: " + this.companyName);
} else {
companyRep = comp.playerReputation;
}
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
" at " + this.companyName + " (Current Company Reputation: " +
formatNumber(companyRep, 0) + ")<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"You have earned: <br><br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * CYCLES_PER_SEC, 4) + " / sec) reputation for this company <br><br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br><br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br><br> " +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br><br>" +
"You will automatically finish after working for 8 hours. You can cancel earlier if you wish, " +
"but you will only gain half of the reputation you've earned so far."
}
PlayerObject.prototype.finishWork = function(cancelled, sing=false) { PlayerObject.prototype.finishWork = function(cancelled, sing=false) {
//Since the work was cancelled early, player only gains half of what they've earned so far //Since the work was cancelled early, player only gains half of what they've earned so far
if (cancelled) { if (cancelled) {
this.workRepGained /= 2; this.workRepGained /= 2;
} }
this.gainWorkExp();
var company = Companies[this.companyName]; var company = Companies[this.companyName];
company.playerReputation += (this.workRepGained); company.playerReputation += (this.workRepGained);
@ -698,91 +786,6 @@ PlayerObject.prototype.finishWork = function(cancelled, sing=false) {
this.resetWorkStatus(); this.resetWorkStatus();
} }
PlayerObject.prototype.startWork = function() {
this.resetWorkStatus();
this.isWorking = true;
this.workType = CONSTANTS.WorkTypeCompany;
this.workHackExpGainRate = this.getWorkHackExpGain();
this.workStrExpGainRate = this.getWorkStrExpGain();
this.workDefExpGainRate = this.getWorkDefExpGain();
this.workDexExpGainRate = this.getWorkDexExpGain();
this.workAgiExpGainRate = this.getWorkAgiExpGain();
this.workChaExpGainRate = this.getWorkChaExpGain();
this.workRepGainRate = this.getWorkRepGain();
this.workMoneyGainRate = this.getWorkMoneyGain();
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
//Remove all old event listeners from Cancel button
var newCancelButton = clearEventListeners("work-in-progress-cancel-button");
newCancelButton.innerHTML = "Cancel Work";
newCancelButton.addEventListener("click", function() {
Player.finishWork(true);
return false;
});
//Display Work In Progress Screen
Engine.loadWorkInProgressContent();
}
PlayerObject.prototype.work = function(numCycles) {
this.workRepGainRate = this.getWorkRepGain();
this.workHackExpGained += this.workHackExpGainRate * numCycles;
this.workStrExpGained += this.workStrExpGainRate * numCycles;
this.workDefExpGained += this.workDefExpGainRate * numCycles;
this.workDexExpGained += this.workDexExpGainRate * numCycles;
this.workAgiExpGained += this.workAgiExpGainRate * numCycles;
this.workChaExpGained += this.workChaExpGainRate * numCycles;
this.workRepGained += this.workRepGainRate * numCycles;
this.workMoneyGained += this.workMoneyGainRate * numCycles;
var cyclesPerSec = 1000 / Engine._idleSpeed;
this.timeWorked += Engine._idleSpeed * numCycles;
//If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money
if (this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
var maxCycles = CONSTANTS.GameCyclesPer8Hours;
this.workHackExpGained = this.workHackExpGainRate * maxCycles;
this.workStrExpGained = this.workStrExpGainRate * maxCycles;
this.workDefExpGained = this.workDefExpGainRate * maxCycles;
this.workDexExpGained = this.workDexExpGainRate * maxCycles;
this.workAgiExpGained = this.workAgiExpGainRate * maxCycles;
this.workChaExpGained = this.workChaExpGainRate * maxCycles;
this.workRepGained = this.workRepGainRate * maxCycles;
this.workMoneyGained = this.workMoneyGainRate * maxCycles;
this.finishWork(false);
return;
}
var comp = Companies[this.companyName], companyRep = "0";
if (comp == null || !(comp instanceof Company)) {
console.log("ERROR: Could not find Company: " + this.companyName);
} else {
companyRep = comp.playerReputation;
}
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
" at " + this.companyName + " (Current Company Reputation: " +
formatNumber(companyRep, 0) + ")<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"You have earned: <br><br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec) <br><br>" +
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this company <br><br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br><br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br><br> " +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br><br>" +
"You will automatically finish after working for 8 hours. You can cancel earlier if you wish, " +
"but you will only gain half of the reputation you've earned so far."
}
PlayerObject.prototype.startWorkPartTime = function() { PlayerObject.prototype.startWorkPartTime = function() {
this.resetWorkStatus(); this.resetWorkStatus();
this.isWorking = true; this.isWorking = true;
@ -811,57 +814,50 @@ PlayerObject.prototype.startWorkPartTime = function() {
} }
PlayerObject.prototype.workPartTime = function(numCycles) { PlayerObject.prototype.workPartTime = function(numCycles) {
this.workRepGainRate = this.getWorkRepGain(); //Cap the number of cycles being processed to whatever would put you at the
//work time limit (8 hours)
this.workHackExpGained += this.workHackExpGainRate * numCycles; var overMax = false;
this.workStrExpGained += this.workStrExpGainRate * numCycles; if (this.timeWorked + (Engine._idleSpeed * numCycles) >= CONSTANTS.MillisecondsPer8Hours) {
this.workDefExpGained += this.workDefExpGainRate * numCycles; overMax = true;
this.workDexExpGained += this.workDexExpGainRate * numCycles; numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / Engine._idleSpeed);
this.workAgiExpGained += this.workAgiExpGainRate * numCycles; }
this.workChaExpGained += this.workChaExpGainRate * numCycles;
this.workRepGained += this.workRepGainRate * numCycles;
this.workMoneyGained += this.workMoneyGainRate * numCycles;
var cyclesPerSec = 1000 / Engine._idleSpeed;
this.timeWorked += Engine._idleSpeed * numCycles; this.timeWorked += Engine._idleSpeed * numCycles;
this.workRepGainRate = this.getWorkRepGain();
this.processWorkEarnings(numCycles);
//If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money //If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money
if (this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) { if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
var maxCycles = CONSTANTS.GameCyclesPer8Hours; return this.finishWorkPartTime();
this.workHackExpGained = this.workHackExpGainRate * maxCycles; }
this.workStrExpGained = this.workStrExpGainRate * maxCycles;
this.workDefExpGained = this.workDefExpGainRate * maxCycles; var comp = Companies[this.companyName], companyRep = "0";
this.workDexExpGained = this.workDexExpGainRate * maxCycles; if (comp == null || !(comp instanceof Company)) {
this.workAgiExpGained = this.workAgiExpGainRate * maxCycles; console.log("ERROR: Could not find Company: " + this.companyName);
this.workChaExpGained = this.workChaExpGainRate * maxCycles; } else {
this.workRepGained = this.workRepGainRate * maxCycles; companyRep = comp.playerReputation;
this.workMoneyGained = this.workMoneyGainRate * maxCycles;
this.finishWorkPartTime();
return;
} }
var txt = document.getElementById("work-in-progress-text"); var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName + txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
" at " + Player.companyName + "<br><br>" + " at " + Player.companyName + " (Current Company Reputation: " +
formatNumber(companyRep, 0) + ")<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" + "You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"You have earned: <br><br>" + "You have earned: <br><br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec) <br><br>" + "$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this company <br><br>" + formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * CYCLES_PER_SEC, 4) + " / sec) reputation for this company <br><br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br><br>" + formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br><br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" + formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" + formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" + formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br><br> " + formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br><br> " +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br><br>" + formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br><br>" +
"You will automatically finish after working for 8 hours. You can cancel earlier if you wish, <br>" + "You will automatically finish after working for 8 hours. You can cancel earlier if you wish, <br>" +
"and there will be no penalty because this is a part-time job."; "and there will be no penalty because this is a part-time job.";
} }
PlayerObject.prototype.finishWorkPartTime = function(sing=false) { PlayerObject.prototype.finishWorkPartTime = function(sing=false) {
this.gainWorkExp();
var company = Companies[this.companyName]; var company = Companies[this.companyName];
company.playerReputation += (this.workRepGained); company.playerReputation += (this.workRepGained);
@ -903,51 +899,6 @@ PlayerObject.prototype.finishWorkPartTime = function(sing=false) {
} }
/* Working for Faction */ /* Working for Faction */
PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
this.gainWorkExp();
var faction = Factions[this.currentWorkFactionName];
faction.playerReputation += (this.workRepGained);
this.gainMoney(this.workMoneyGained);
this.updateSkillLevels();
var txt = "You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " +
"You earned a total of: <br>" +
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
formatNumber(this.workRepGained, 4) + " reputation for the faction <br>" +
formatNumber(this.workHackExpGained, 4) + " hacking exp <br>" +
formatNumber(this.workStrExpGained, 4) + " strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " charisma exp<br>";
if (!sing) {dialogBoxCreate(txt);}
var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible";
this.isWorking = false;
Engine.loadFactionContent();
displayFactionContent(faction.name);
if (sing) {
var res="You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + ". " +
"You earned " +
formatNumber(this.workRepGained, 4) + " rep, " +
formatNumber(this.workHackExpGained, 4) + " hacking exp, " +
formatNumber(this.workStrExpGained, 4) + " str exp, " +
formatNumber(this.workDefExpGained, 4) + " def exp, " +
formatNumber(this.workDexExpGained, 4) + " dex exp, " +
formatNumber(this.workAgiExpGained, 4) + " agi exp, and " +
formatNumber(this.workChaExpGained, 4) + " cha exp.";
this.resetWorkStatus();
return res;
}
this.resetWorkStatus();
}
PlayerObject.prototype.startFactionWork = function(faction) { PlayerObject.prototype.startFactionWork = function(faction) {
//Update reputation gain rate to account for faction favor //Update reputation gain rate to account for faction favor
var favorMult = 1 + (faction.favor / 100); var favorMult = 1 + (faction.favor / 100);
@ -1042,32 +993,19 @@ PlayerObject.prototype.workForFaction = function(numCycles) {
this.workRepGainRate *= favorMult; this.workRepGainRate *= favorMult;
this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain; this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain;
this.workHackExpGained += this.workHackExpGainRate * numCycles; //Cap the number of cycles being processed to whatever would put you at limit (20 hours)
this.workStrExpGained += this.workStrExpGainRate * numCycles; var overMax = false;
this.workDefExpGained += this.workDefExpGainRate * numCycles; if (this.timeWorked + (Engine._idleSpeed * numCycles) >= CONSTANTS.MillisecondsPer20Hours) {
this.workDexExpGained += this.workDexExpGainRate * numCycles; overMax = true;
this.workAgiExpGained += this.workAgiExpGainRate * numCycles; numCycles = Math.round((CONSTANTS.MillisecondsPer20Hours - this.timeWorked) / Engine._idleSpeed);
this.workChaExpGained += this.workChaExpGainRate * numCycles; }
this.workRepGained += this.workRepGainRate * numCycles;
this.workMoneyGained += this.workMoneyGainRate * numCycles;
var cyclesPerSec = 1000 / Engine._idleSpeed;
this.timeWorked += Engine._idleSpeed * numCycles; this.timeWorked += Engine._idleSpeed * numCycles;
this.processWorkEarnings(numCycles);
//If timeWorked == 20 hours, then finish. You can only work for the faction for 20 hours //If timeWorked == 20 hours, then finish. You can only work for the faction for 20 hours
if (this.timeWorked >= CONSTANTS.MillisecondsPer20Hours) { if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer20Hours) {
var maxCycles = CONSTANTS.GameCyclesPer20Hours; return this.finishWork(false);
this.timeWorked = CONSTANTS.MillisecondsPer20Hours;
this.workHackExpGained = this.workHackExpGainRate * maxCycles;
this.workStrExpGained = this.workStrExpGainRate * maxCycles;
this.workDefExpGained = this.workDefExpGainRate * maxCycles;
this.workDexExpGained = this.workDexExpGainRate * maxCycles;
this.workAgiExpGained = this.workAgiExpGainRate * maxCycles;
this.workChaExpGained = this.workChaExpGainRate * maxCycles;
this.workRepGained = this.workRepGainRate * maxCycles;
this.workMoneyGained = this.workMoneyGainRate * maxCycles;
this.finishFactionWork(false);
} }
var txt = document.getElementById("work-in-progress-text"); var txt = document.getElementById("work-in-progress-text");
@ -1075,19 +1013,61 @@ PlayerObject.prototype.workForFaction = function(numCycles) {
" (Current Faction Reputation: " + formatNumber(faction.playerReputation, 0) + "). " + " (Current Faction Reputation: " + formatNumber(faction.playerReputation, 0) + "). " +
"You have been doing this for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" + "You have been doing this for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"You have earned: <br><br>" + "You have earned: <br><br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " (" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec) <br><br>" + "$" + formatNumber(this.workMoneyGained, 2) + " (" + formatNumber(this.workMoneyGainRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this faction <br><br>" + formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * CYCLES_PER_SEC, 4) + " / sec) reputation for this faction <br><br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br><br>" + formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br><br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" + formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" + formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" + formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br><br> " + formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br><br> " +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br><br>" + formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br><br>" +
"You will automatically finish after working for 20 hours. You can cancel earlier if you wish.<br>" + "You will automatically finish after working for 20 hours. You can cancel earlier if you wish.<br>" +
"There is no penalty for cancelling earlier."; "There is no penalty for cancelling earlier.";
} }
PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
var faction = Factions[this.currentWorkFactionName];
faction.playerReputation += (this.workRepGained);
this.gainMoney(this.workMoneyGained);
this.updateSkillLevels();
var txt = "You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " +
"You earned a total of: <br>" +
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
formatNumber(this.workRepGained, 4) + " reputation for the faction <br>" +
formatNumber(this.workHackExpGained, 4) + " hacking exp <br>" +
formatNumber(this.workStrExpGained, 4) + " strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " charisma exp<br>";
if (!sing) {dialogBoxCreate(txt);}
var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible";
this.isWorking = false;
Engine.loadFactionContent();
displayFactionContent(faction.name);
if (sing) {
var res="You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + ". " +
"You earned " +
formatNumber(this.workRepGained, 4) + " rep, " +
formatNumber(this.workHackExpGained, 4) + " hacking exp, " +
formatNumber(this.workStrExpGained, 4) + " str exp, " +
formatNumber(this.workDefExpGained, 4) + " def exp, " +
formatNumber(this.workDexExpGained, 4) + " dex exp, " +
formatNumber(this.workAgiExpGained, 4) + " agi exp, and " +
formatNumber(this.workChaExpGained, 4) + " cha exp.";
this.resetWorkStatus();
return res;
}
this.resetWorkStatus();
}
//Money gained per game cycle //Money gained per game cycle
PlayerObject.prototype.getWorkMoneyGain = function() { PlayerObject.prototype.getWorkMoneyGain = function() {
@ -1363,36 +1343,25 @@ PlayerObject.prototype.takeClass = function(numCycles) {
this.timeWorked += Engine._idleSpeed * numCycles; this.timeWorked += Engine._idleSpeed * numCycles;
var className = this.className; var className = this.className;
this.workHackExpGained += this.workHackExpGainRate * numCycles; this.processWorkEarnings(numCycles);
this.workStrExpGained += this.workStrExpGainRate * numCycles;
this.workDefExpGained += this.workDefExpGainRate * numCycles;
this.workDexExpGained += this.workDexExpGainRate * numCycles;
this.workAgiExpGained += this.workAgiExpGainRate * numCycles;
this.workChaExpGained += this.workChaExpGainRate * numCycles;
this.workRepGained += this.workRepGainRate * numCycles;
this.workMoneyGained += this.workMoneyGainRate * numCycles;
this.workMoneyGained -= this.workMoneyLossRate * numCycles;
var cyclesPerSec = 1000 / Engine._idleSpeed;
var txt = document.getElementById("work-in-progress-text"); var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You have been " + className + " for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" + txt.innerHTML = "You have been " + className + " for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"This has cost you: <br>" + "This has cost you: <br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyLossRate * cyclesPerSec, 2) + " / sec) <br><br>" + "$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyLossRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
"You have gained: <br>" + "You have gained: <br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br>" + formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" + formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" + formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" + formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br>" + formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br>" + formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br>" +
"You may cancel at any time"; "You may cancel at any time";
} }
//The 'sing' argument defines whether or not this function was called //The 'sing' argument defines whether or not this function was called
//through a Singularity Netscript function //through a Singularity Netscript function
PlayerObject.prototype.finishClass = function(sing=false) { PlayerObject.prototype.finishClass = function(sing=false) {
this.gainWorkExp();
this.gainIntelligenceExp(CONSTANTS.IntelligenceClassBaseExpGain * Math.round(this.timeWorked / 1000)); this.gainIntelligenceExp(CONSTANTS.IntelligenceClassBaseExpGain * Math.round(this.timeWorked / 1000));
if (this.workMoneyGained > 0) { if (this.workMoneyGained > 0) {
@ -1567,7 +1536,12 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
} }
} }
this.gainWorkExp(); this.gainHackingExp(this.workHackExpGained);
this.gainStrengthExp(this.workStrExpGained);
this.gainDefenseExp(this.workDefExpGained);
this.gainDexterityExp(this.workDexExpGained);
this.gainAgilityExp(this.workAgiExpGained);
this.gainCharismaExp(this.workChaExpGained);
} }
this.committingCrimeThruSingFn = false; this.committingCrimeThruSingFn = false;
this.singFnCrimeWorkerScript = null; this.singFnCrimeWorkerScript = null;